def test_empty_student_progress_stats_analytics_displays_nothing(self): """Test analytics page on course dashboard when no progress stats.""" # The admin looks at the analytics page on the board to check right # message when no progress has been recorded. email = '*****@*****.**' actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics_students') assert_contains('Google > Dashboard > Manage > Students', response.body) assert_contains('have not been calculated yet', response.body) response = response.forms['gcb-generate-analytics-data'].submit( ).follow() assert len(self.taskq.GetTasks('default')) == ( ProgressAnalyticsTest.EXPECTED_TASK_COUNT) assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get(response.request.url) assert_contains('were last updated at', response.body) assert_contains('currently enrolled: 0', response.body) assert_contains('total: 0', response.body) assert_contains('Student Progress', response.body) assert_contains( 'No student progress has been recorded for this course.', response.body) actions.logout()
def test_empty_student_progress_stats_analytics_displays_nothing(self): """Test analytics page on course dashboard when no progress stats.""" # The admin looks at the analytics page on the board to check right # message when no progress has been recorded. email = '*****@*****.**' actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics') assert_contains( 'Google > Dashboard > Analytics', response.body) assert_contains('have not been calculated yet', response.body) compute_form = response.forms['gcb-compute-student-stats'] response = self.submit(compute_form) assert_equals(response.status_int, 302) assert len(self.taskq.GetTasks('default')) == 4 response = self.get('dashboard?action=analytics') assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get('dashboard?action=analytics') assert_contains('were last updated at', response.body) assert_contains('currently enrolled: 0', response.body) assert_contains('total: 0', response.body) assert_contains('Student Progress Statistics', response.body) assert_contains( 'No student progress has been recorded for this course.', response.body) actions.logout()
def setUp(self): super(DashboardAccessTestCase, self).setUp() actions.login(self.ADMIN_EMAIL, is_admin=True) context = actions.simple_add_course( self.ACCESS_COURSE_NAME, self.ADMIN_EMAIL, 'Course with access') self.course_with_access = courses.Course(None, context) with Namespace(self.course_with_access.app_context.namespace): role_dto = models.RoleDTO(None, { 'name': self.ROLE, 'users': [self.USER_EMAIL], 'permissions': {dashboard.custom_module.name: [self.PERMISSION]} }) models.RoleDAO.save(role_dto) context = actions.simple_add_course( self.NO_ACCESS_COURSE_NAME, self.ADMIN_EMAIL, 'Course with no access' ) self.course_without_access = courses.Course(None, context) # pylint: disable=W0212 self.old_nav_mappings = DashboardHandler._nav_mappings # pylint: disable=W0212 DashboardHandler._nav_mappings = {self.ACTION: 'outline'} DashboardHandler.map_action_to_permission( 'get_%s' % self.ACTION, self.PERMISSION) actions.logout()
def test_student_cannot_see_reviews_prematurely(self): """Test that students cannot see others' reviews prematurely.""" email = '*****@*****.**' name = 'Student 1' submission = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True}, ]) payload = { 'answers': submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload) # Student 1 cannot see the reviews for his assignment yet, because he # has not submitted the two required reviews. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('Due date for this assignment', response.body) assert_contains( 'After you have completed the required number of peer reviews', response.body) actions.logout()
def test_student_cannot_see_reviews_prematurely(self): """Test that students cannot see others' reviews prematurely.""" email = "*****@*****.**" name = "Student 1" submission = transforms.dumps( [ {"index": 0, "type": "regex", "value": "S1-1", "correct": True}, {"index": 1, "type": "choices", "value": 3, "correct": False}, {"index": 2, "type": "regex", "value": "is-S1", "correct": True}, ] ) payload = {"answers": submission, "assessment_type": LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload) # Student 1 cannot see the reviews for his assignment yet, because he # has not submitted the two required reviews. response = self.get("assessment?name=%s" % LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains("Due date for this assignment", response.body) assert_contains("After you have completed the required number of peer reviews", response.body) actions.logout()
def test_not_enough_assignments_to_allocate(self): """Test for the case when there are too few assignments in the pool.""" email = '*****@*****.**' name = 'Student 1' submission = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True}, ]) payload = { 'answers': submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload) # The student goes to the review dashboard and requests an assignment # to review -- but there is nothing to review. response = actions.request_new_review( self, LEGACY_REVIEW_UNIT_ID, expected_status_code=200) assert_does_not_contain('Assignment to review', response.body) assert_contains('Sorry, there are no new submissions ', response.body) assert_contains('disabled="true"', response.body) actions.logout()
def test_not_enough_assignments_to_allocate(self): """Test for the case when there are too few assignments in the pool.""" email = "*****@*****.**" name = "Student 1" submission = transforms.dumps( [ {"index": 0, "type": "regex", "value": "S1-1", "correct": True}, {"index": 1, "type": "choices", "value": 3, "correct": False}, {"index": 2, "type": "regex", "value": "is-S1", "correct": True}, ] ) payload = {"answers": submission, "assessment_type": LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload) # The student goes to the review dashboard and requests an assignment # to review -- but there is nothing to review. response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID, expected_status_code=200) assert_does_not_contain("Assignment to review", response.body) assert_contains("Sorry, there are no new submissions ", response.body) assert_contains('disabled="true"', response.body) actions.logout()
def test_empty_student_progress_stats_analytics_displays_nothing(self): """Test analytics page on course dashboard when no progress stats.""" # The admin looks at the analytics page on the board to check right # message when no progress has been recorded. email = '*****@*****.**' actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics&tab=students') assert_contains( 'Google > Dashboard > Analytics > Students', response.body) assert_contains('have not been calculated yet', response.body) response = response.forms[ 'gcb-generate-analytics-data'].submit().follow() assert len(self.taskq.GetTasks('default')) == ( ProgressAnalyticsTest.EXPECTED_TASK_COUNT) assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get(response.request.url) assert_contains('were last updated at', response.body) assert_contains('currently enrolled: 0', response.body) assert_contains('total: 0', response.body) assert_contains('Student Progress', response.body) assert_contains( 'No student progress has been recorded for this course.', response.body) actions.logout()
def setUp(self): super(DashboardAccessTestCase, self).setUp() actions.login(self.ADMIN_EMAIL, is_admin=True) context = actions.simple_add_course( self.ACCESS_COURSE_NAME, self.ADMIN_EMAIL, 'Course with access') self.course_with_access = courses.Course(None, context) with Namespace(self.course_with_access.app_context.namespace): role_dto = models.RoleDTO(None, { 'name': self.ROLE, 'users': [self.USER_EMAIL], 'permissions': {dashboard.custom_module.name: [self.PERMISSION]} }) models.RoleDAO.save(role_dto) context = actions.simple_add_course( self.NO_ACCESS_COURSE_NAME, self.ADMIN_EMAIL, 'Course with no access' ) self.course_without_access = courses.Course(None, context) # pylint: disable=W0212 self.old_nav_mappings = DashboardHandler._custom_nav_mappings # pylint: disable=W0212 DashboardHandler._custom_nav_mappings = {self.ACTION: 'outline'} DashboardHandler.map_action_to_permission( 'get_%s' % self.ACTION, self.PERMISSION) actions.logout()
def test_student_progress_stats_analytics_displays_on_dashboard(self): """Test analytics page on course dashboard.""" with actions.OverriddenEnvironment( {'course': { analytics.CAN_RECORD_STUDENT_EVENTS: 'true' }}): student1 = '*****@*****.**' name1 = 'Test Student 1' student2 = '*****@*****.**' name2 = 'Test Student 2' # Student 1 completes a unit. actions.login(student1) actions.register(self, name1) actions.view_unit(self) actions.logout() # Student 2 completes a unit. actions.login(student2) actions.register(self, name2) actions.view_unit(self) actions.logout() # Admin logs back in and checks if progress exists. email = '*****@*****.**' actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics_students') assert_contains('Google > Dashboard > Manage > Students', response.body) assert_contains('have not been calculated yet', response.body) response = response.forms['gcb-generate-analytics-data'].submit( ).follow() assert len(self.taskq.GetTasks('default')) == ( ProgressAnalyticsTest.EXPECTED_TASK_COUNT) response = self.get('dashboard?action=analytics_students') assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get('dashboard?action=analytics_students') assert_contains('were last updated at', response.body) assert_contains('currently enrolled: 2', response.body) assert_contains('total: 2', response.body) assert_contains('Student Progress', response.body) assert_does_not_contain( 'No student progress has been recorded for this course.', response.body) # JSON code for the completion statistics. assert_contains( '\\"u.1.l.1\\": {\\"progress\\": 0, \\"completed\\": 2}', response.body) assert_contains( '\\"u.1\\": {\\"progress\\": 2, \\"completed\\": 0}', response.body)
def test_student_progress_stats_analytics_displays_on_dashboard(self): """Test analytics page on course dashboard.""" with actions.OverriddenEnvironment( {'course': {analytics.CAN_RECORD_STUDENT_EVENTS: 'true'}}): student1 = '*****@*****.**' name1 = 'Test Student 1' student2 = '*****@*****.**' name2 = 'Test Student 2' # Student 1 completes a unit. actions.login(student1) actions.register(self, name1) actions.view_unit(self) actions.logout() # Student 2 completes a unit. actions.login(student2) actions.register(self, name2) actions.view_unit(self) actions.logout() # Admin logs back in and checks if progress exists. email = '*****@*****.**' actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics_students') assert_contains( 'Google > Dashboard > Manage > Students', response.body) assert_contains('have not been calculated yet', response.body) response = response.forms[ 'gcb-generate-analytics-data'].submit().follow() assert len(self.taskq.GetTasks('default')) == ( ProgressAnalyticsTest.EXPECTED_TASK_COUNT) response = self.get('dashboard?action=analytics_students') assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get('dashboard?action=analytics_students') assert_contains('were last updated at', response.body) assert_contains('currently enrolled: 2', response.body) assert_contains('total: 2', response.body) assert_contains('Student Progress', response.body) assert_does_not_contain( 'No student progress has been recorded for this course.', response.body) # JSON code for the completion statistics. assert_contains( '\\"u.1.l.1\\": {\\"progress\\": 0, \\"completed\\": 2}', response.body) assert_contains( '\\"u.1\\": {\\"progress\\": 2, \\"completed\\": 0}', response.body)
def test_student_progress_stats_analytics_displays_on_dashboard(self): """Test analytics page on course dashboard.""" self.enable_progress_tracking() student1 = '*****@*****.**' name1 = 'Test Student 1' student2 = '*****@*****.**' name2 = 'Test Student 2' # Student 1 completes a unit. actions.login(student1) actions.register(self, name1) actions.view_unit(self) actions.logout() # Student 2 completes a unit. actions.login(student2) actions.register(self, name2) actions.view_unit(self) actions.logout() # Admin logs back in and checks if progress exists. email = '*****@*****.**' actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics') assert_contains( 'Google ><a href="%s"> Dashboard </a>> Analytics' % self.canonicalize('dashboard'), response.body) assert_contains('have not been calculated yet', response.body) compute_form = response.forms['gcb-compute-student-stats'] response = self.submit(compute_form) assert_equals(response.status_int, 302) assert len(self.taskq.GetTasks('default')) == 5 response = self.get('dashboard?action=analytics') assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get('dashboard?action=analytics') assert_contains('were last updated at', response.body) assert_contains('currently enrolled: 2', response.body) assert_contains('total: 2', response.body) assert_contains('Student Progress Statistics', response.body) assert_does_not_contain( 'No student progress has been recorded for this course.', response.body) # JSON code for the completion statistics. assert_contains( '\\"u.1.l.1\\": {\\"progress\\": 0, \\"completed\\": 2}', response.body) assert_contains( '\\"u.1\\": {\\"progress\\": 2, \\"completed\\": 0}', response.body)
def test_student_progress_stats_analytics_displays_on_dashboard(self): """Test analytics page on course dashboard.""" self.enable_progress_tracking() student1 = '*****@*****.**' name1 = 'Test Student 1' student2 = '*****@*****.**' name2 = 'Test Student 2' # Student 1 completes a unit. actions.login(student1) actions.register(self, name1) actions.view_unit(self) actions.logout() # Student 2 completes a unit. actions.login(student2) actions.register(self, name2) actions.view_unit(self) actions.logout() # Admin logs back in and checks if progress exists. email = '*****@*****.**' actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics') assert_contains( 'Google > Dashboard > Analytics', response.body) assert_contains('have not been calculated yet', response.body) compute_form = response.forms['gcb-compute-student-stats'] response = self.submit(compute_form) assert_equals(response.status_int, 302) assert len(self.taskq.GetTasks('default')) == 4 response = self.get('dashboard?action=analytics') assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get('dashboard?action=analytics') assert_contains('were last updated at', response.body) assert_contains('currently enrolled: 2', response.body) assert_contains('total: 2', response.body) assert_contains('Student Progress Statistics', response.body) assert_does_not_contain( 'No student progress has been recorded for this course.', response.body) # JSON code for the completion statistics. assert_contains( '\\"u.1.l.1\\": {\\"progress\\": 0, \\"completed\\": 2}', response.body) assert_contains( '\\"u.1\\": {\\"progress\\": 2, \\"completed\\": 0}', response.body)
def test_access_assessment(self): assessment = self.course.add_assessment() assessment.is_draft = True self.course.save() self.assertEquals( self.get('assessment?name=%s' % assessment.unit_id).status_int, 302) actions.login(self.USER_EMAIL, is_admin=False) self.assertEquals( self.get('assessment?name=%s' % assessment.unit_id).status_int, 200) actions.logout()
def test_login_and_logout(self): """Test if login and logout behave as expected.""" email = '*****@*****.**' actions.Permissions.assert_logged_out(self) actions.login(email) actions.Permissions.assert_unenrolled(self) actions.logout() actions.Permissions.assert_logged_out(self)
def test_course_picker(self): actions.login(self.USER_EMAIL, is_admin=False) picker_options = self._get_all_picker_options() self.assertEquals(len(list(picker_options)), 0) actions.logout() actions.login(self.ADMIN_EMAIL, is_admin=True) picker_options = self._get_all_picker_options() # Expect 3 courses, as the default one is also considered for the picker self.assertEquals(len(picker_options), 2) actions.logout()
def setUp(self): super(DashboardAccessTestCase, self).setUp() actions.login(self.ADMIN_EMAIL, is_admin=True) context = actions.simple_add_course(self.ACCESS_COURSE_NAME, self.ADMIN_EMAIL, 'Course with access') self.course_with_access = courses.Course(None, context) with Namespace(self.course_with_access.app_context.namespace): role_dto = models.RoleDTO( None, { 'name': self.ROLE, 'users': [self.USER_EMAIL], 'permissions': { dashboard.custom_module.name: [self.PERMISSION] } }) models.RoleDAO.save(role_dto) context = actions.simple_add_course(self.NO_ACCESS_COURSE_NAME, self.ADMIN_EMAIL, 'Course with no access') self.course_without_access = courses.Course(None, context) def test_content(self): return self.render_page({ 'main_content': 'test', 'page_title': 'test' }) # save properties self.old_menu_group = DashboardHandler.root_menu_group # pylint: disable=W0212 self.old_get_acitons = DashboardHandler._custom_get_actions # pylint: enable=W0212 # put a dummy method in menu_group = menus.MenuGroup('test', 'Test Dashboard') DashboardHandler.root_menu_group = menu_group DashboardHandler.default_action = self.ACTION DashboardHandler.add_nav_mapping(self.ACTION, self.ACTION) DashboardHandler.add_sub_nav_mapping(self.ACTION, self.ACTION, self.ACTION, action=self.ACTION, contents=test_content) DashboardHandler.map_action_to_permission('get_%s' % self.ACTION, self.PERMISSION) actions.logout()
def test_course_picker(self): actions.login(self.USER_EMAIL, is_admin=False) picker_options = self._get_all_picker_options() self.assertEquals(len(list(picker_options)), 1) self.assertEquals(picker_options[0].get( 'href'), '/%s/dashboard?action=outline' % self.ACCESS_COURSE_NAME) actions.logout() actions.login(self.ADMIN_EMAIL, is_admin=True) picker_options = self._get_all_picker_options() # Expect 3 courses, as the default one is also considered for the picker self.assertEquals(len(picker_options), 3) actions.logout()
def test_course_picker(self): actions.login(self.USER_EMAIL, is_admin=False) picker_options = self._get_all_picker_options() self.assertEquals(len(list(picker_options)), 1) self.assertEquals(picker_options[0].get( 'href'), '/%s/dashboard' % self.ACCESS_COURSE_NAME) actions.logout() actions.login(self.ADMIN_EMAIL, is_admin=True) picker_options = self._get_all_picker_options() # Expect 3 courses, as the default one is also considered for the picker self.assertEquals(len(picker_options), 3) actions.logout()
def test_access_lesson(self): unit = self.course.add_unit() unit.is_draft = True lesson = self.course.add_lesson(unit) lesson.is_draft = True self.course.save() self.assertEquals( self.get('unit?unit=%s&lesson=%s' % ( unit.unit_id, lesson.lesson_id)).status_int, 302) actions.login(self.USER_EMAIL, is_admin=False) self.assertEquals( self.get('unit?unit=%s&lesson=%s' % ( unit.unit_id, lesson.lesson_id)).status_int, 200) actions.logout()
def test_access_lesson(self): unit = self.course.add_unit() unit.is_draft = True lesson = self.course.add_lesson(unit) lesson.is_draft = True self.course.save() self.assertEquals( self.get('unit?unit=%s&lesson=%s' % (unit.unit_id, lesson.lesson_id)).status_int, 302) actions.login(self.USER_EMAIL, is_admin=False) self.assertEquals( self.get('unit?unit=%s&lesson=%s' % (unit.unit_id, lesson.lesson_id)).status_int, 200) actions.logout()
def test_dashboard_access_method(self): with Namespace(self.course_with_access.app_context.namespace): self.assertFalse(DashboardHandler.current_user_has_access( self.course_with_access.app_context)) with Namespace(self.course_without_access.app_context.namespace): self.assertFalse(DashboardHandler.current_user_has_access( self.course_without_access.app_context)) actions.login(self.USER_EMAIL, is_admin=False) with Namespace(self.course_with_access.app_context.namespace): self.assertTrue(DashboardHandler.current_user_has_access( self.course_with_access.app_context)) with Namespace(self.course_without_access.app_context.namespace): self.assertFalse(DashboardHandler.current_user_has_access( self.course_without_access.app_context)) actions.logout()
def walk_the_course( self, course, first_time=True, is_admin=False, logout=True): """Visit a course as a Student would.""" # Check normal user has no access. actions.login(course.email, is_admin) # Test schedule. if first_time: response = self.testapp.get('/courses/%s/preview' % course.path) else: response = self.testapp.get('/courses/%s/course' % course.path) assert_contains(course.title, response.body) assert_contains(course.unit_title, response.body) assert_contains(course.head, response.body) # Tests static resource. response = self.testapp.get( '/courses/%s/assets/css/main.css' % course.path) assert_contains(course.css, response.body) if first_time: # Test registration. response = self.get('/courses/%s/register' % course.path) assert_contains(course.title, response.body) assert_contains(course.head, response.body) response.form.set('form01', course.name) response.form.action = '/courses/%s/register' % course.path response = self.submit(response.form) assert_contains(course.title, response.body) assert_contains(course.head, response.body) assert_contains(course.title, response.body) assert_contains( '//groups.google.com/group/My-Course-Announce', response.body) assert_contains( '//groups.google.com/group/My-Course', response.body) # Check lesson page. response = self.testapp.get( '/courses/%s/unit?unit=1&lesson=5' % course.path) assert_contains(course.title, response.body) assert_contains(course.lesson_title, response.body) assert_contains(course.head, response.body) if logout: actions.logout()
def test_add_reviewer(self): """Test that admin can add a reviewer, and cannot re-add reviewers.""" email = '*****@*****.**' name = 'Test Add Reviewer' submission = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'First answer to Q1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'First answer to Q3', 'correct': True}, ]) payload = { 'answers': submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload) # There is nothing to review on the review dashboard. response = actions.request_new_review( self, LEGACY_REVIEW_UNIT_ID, expected_status_code=200) assert_does_not_contain('Assignment to review', response.body) assert_contains('Sorry, there are no new submissions ', response.body) actions.logout() # The admin assigns the student to review his own work. actions.login(email, is_admin=True) response = actions.add_reviewer( self, LEGACY_REVIEW_UNIT_ID, email, email) assert_equals(response.status_int, 302) response = self.get(response.location) assert_does_not_contain( 'Error 412: The reviewer is already assigned', response.body) assert_contains('First answer to Q1', response.body) assert_contains( 'Review 1 from [email protected]', response.body) # The admin repeats the 'add reviewer' action. This should fail. response = actions.add_reviewer( self, LEGACY_REVIEW_UNIT_ID, email, email) assert_equals(response.status_int, 302) response = self.get(response.location) assert_contains( 'Error 412: The reviewer is already assigned', response.body)
def setUp(self): super(DashboardAccessTestCase, self).setUp() actions.login(self.ADMIN_EMAIL, is_admin=True) context = actions.simple_add_course( self.ACCESS_COURSE_NAME, self.ADMIN_EMAIL, 'Course with access') self.course_with_access = courses.Course(None, context) with Namespace(self.course_with_access.app_context.namespace): role_dto = models.RoleDTO(None, { 'name': self.ROLE, 'users': [self.USER_EMAIL], 'permissions': {dashboard.custom_module.name: [self.PERMISSION]} }) models.RoleDAO.save(role_dto) context = actions.simple_add_course( self.NO_ACCESS_COURSE_NAME, self.ADMIN_EMAIL, 'Course with no access' ) self.course_without_access = courses.Course(None, context) def test_content(self): return self.render_page( {'main_content': 'test', 'page_title': 'test'}) # save properties self.old_menu_group = DashboardHandler.root_menu_group # pylint: disable=W0212 self.old_get_acitons = DashboardHandler._custom_get_actions # pylint: enable=W0212 # put a dummy method in menu_group = menus.MenuGroup('test', 'Test Dashboard') DashboardHandler.root_menu_group = menu_group DashboardHandler.default_action = self.ACTION DashboardHandler.add_nav_mapping(self.ACTION, self.ACTION) DashboardHandler.add_sub_nav_mapping(self.ACTION, self.ACTION, self.ACTION, action=self.ACTION, contents=test_content) DashboardHandler.map_action_to_permission( 'get_%s' % self.ACTION, self.PERMISSION) actions.logout()
def test_csv_supports_utf8(self): """Test UTF-8 content in CSV file is handled correctly.""" title_ru = u'Найди факты быстрее' csv_file = os.path.join(self.course_ru.home, 'data/unit.csv') self.modify_file( csv_file, ',Find facts faster,', ',%s,' % title_ru) self.modify_file( os.path.join(self.course_ru.home, 'data/lesson.csv'), ',Find facts faster,', ',%s,' % title_ru) rows = [] for row in csv.reader(open(csv_file)): rows.append(row) assert title_ru == rows[6][3].decode('utf-8') response = self.get('/courses/%s/preview' % self.course_ru.path) assert_contains(title_ru, response.body) # Tests student perspective. self.walk_the_course(self.course_ru, first_time=True) self.walk_the_course(self.course_ru, first_time=False) # Test course author dashboard. self.walk_the_course( self.course_ru, first_time=False, is_admin=True, logout=False) def assert_page_contains(page_name, text_array): dashboard_url = '/courses/%s/dashboard' % self.course_ru.path response = self.get('%s?action=%s' % (dashboard_url, page_name)) for text in text_array: assert_contains(text, response.body) assert_page_contains('', [ title_ru, self.course_ru.unit_title, self.course_ru.lesson_title]) assert_page_contains( 'assets', [self.course_ru.title, self.course_ru.home]) assert_page_contains( 'settings', [self.course_ru.title, self.course_ru.home]) # Clean up. actions.logout()
def test_handling_of_fake_review_step_key(self): """Test that bad keys result in the appropriate responses.""" email = "*****@*****.**" name = "Student 1" submission = transforms.dumps( [ {"index": 0, "type": "regex", "value": "S1-1", "correct": True}, {"index": 1, "type": "choices", "value": 3, "correct": False}, {"index": 2, "type": "regex", "value": "is-S1", "correct": True}, ] ) payload = {"answers": submission, "assessment_type": LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload) actions.view_review(self, LEGACY_REVIEW_UNIT_ID, "Fake key", expected_status_code=404) actions.logout()
def test_handling_of_fake_review_step_key(self): """Test that bad keys result in the appropriate responses.""" email = '*****@*****.**' name = 'Student 1' submission = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True }, ]) payload = { 'answers': submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID } actions.login(email) actions.register(self, name) actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload) actions.view_review(self, LEGACY_REVIEW_UNIT_ID, 'Fake key', expected_status_code=404) actions.logout()
def test_access_to_admin_pages(self): """Test access to admin pages.""" # assert anonymous user has no access response = self.testapp.get('/admin?action=settings') assert_equals(response.status_int, 302) # assert admin user has access email = '*****@*****.**' name = 'Test Access to Admin Pages' actions.login(email, True) actions.register(self, name) response = self.testapp.get('/admin') assert_contains('Power Searching with Google', response.body) assert_contains('All Courses', response.body) response = self.testapp.get('/admin?action=settings') assert_contains('gcb_admin_user_emails', response.body) assert_contains('gcb_config_update_interval_sec', response.body) assert_contains('All Settings', response.body) response = self.testapp.get('/admin?action=perf') assert_contains('gcb-admin-uptime-sec:', response.body) assert_contains('In-process Performance Counters', response.body) response = self.testapp.get('/admin?action=deployment') assert_contains('application_id: testbed-test', response.body) assert_contains('About the Application', response.body) actions.unregister(self) actions.logout() # assert not-admin user has no access actions.login(email) actions.register(self, name) response = self.testapp.get('/admin?action=settings') assert_equals(response.status_int, 302)
def test_handling_of_fake_review_step_key(self): """Test that bad keys result in the appropriate responses.""" email = '*****@*****.**' name = 'Student 1' submission = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True}, ]) payload = { 'answers': submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload) actions.view_review( self, LEGACY_REVIEW_UNIT_ID, 'Fake key', expected_status_code=404) actions.logout()
def setUp(self): super(AccessDraftsTestCase, self).setUp() actions.login(self.ADMIN_EMAIL, is_admin=True) self.base = '/' + self.COURSE_NAME self.context = actions.simple_add_course( self.COURSE_NAME, self.ADMIN_EMAIL, 'Access Draft Testing') self.course = courses.Course(None, self.context) self.old_namespace = namespace_manager.get_namespace() namespace_manager.set_namespace('ns_%s' % self.COURSE_NAME) role_dto = models.RoleDTO(None, { 'name': self.ROLE, 'users': [self.USER_EMAIL], 'permissions': { custom_modules.core_module.name: [ custom_modules.SEE_DRAFTS_PERMISSION] } }) models.RoleDAO.save(role_dto) actions.logout()
def test_add_reviewer(self): """Test that admin can add a reviewer, and cannot re-add reviewers.""" email = "*****@*****.**" name = "Test Add Reviewer" submission = transforms.dumps( [ {"index": 0, "type": "regex", "value": "First answer to Q1", "correct": True}, {"index": 1, "type": "choices", "value": 3, "correct": False}, {"index": 2, "type": "regex", "value": "First answer to Q3", "correct": True}, ] ) payload = {"answers": submission, "assessment_type": LEGACY_REVIEW_UNIT_ID} actions.login(email) actions.register(self, name) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload) # There is nothing to review on the review dashboard. response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID, expected_status_code=200) assert_does_not_contain("Assignment to review", response.body) assert_contains("Sorry, there are no new submissions ", response.body) actions.logout() # The admin assigns the student to review his own work. actions.login(email, is_admin=True) response = actions.add_reviewer(self, LEGACY_REVIEW_UNIT_ID, email, email) assert_equals(response.status_int, 302) response = self.get(response.location) assert_does_not_contain("Error 412: The reviewer is already assigned", response.body) assert_contains("First answer to Q1", response.body) assert_contains("Review 1 from [email protected]", response.body) # The admin repeats the 'add reviewer' action. This should fail. response = actions.add_reviewer(self, LEGACY_REVIEW_UNIT_ID, email, email) assert_equals(response.status_int, 302) response = self.get(response.location) assert_contains("Error 412: The reviewer is already assigned", response.body)
def test_view_announcements(self): """Test student aspect of announcements.""" email = '*****@*****.**' name = 'Test Announcements' actions.login(email) actions.register(self, name) # Check no announcements yet. response = actions.view_announcements(self) assert_does_not_contain('Example Announcement', response.body) assert_does_not_contain('Welcome to the final class!', response.body) assert_contains('No announcements yet.', response.body) actions.logout() # Login as admin and add announcements. actions.login('*****@*****.**', True) actions.register(self, 'admin') response = actions.view_announcements(self) actions.logout() # Check we can see non-draft announcements. actions.login(email) response = actions.view_announcements(self) assert_contains('Example Announcement', response.body) assert_does_not_contain('Welcome to the final class!', response.body) assert_does_not_contain('No announcements yet.', response.body) # Check no access to access to draft announcements via REST handler. items = AnnouncementEntity.all().fetch(1000) for item in items: response = self.get('rest/announcements/item?key=%s' % item.key()) if item.is_draft: json_dict = json.loads(response.body) assert json_dict['status'] == 401 else: assert_equals(response.status_int, 200)
def test_two_students_dont_see_each_other_pages(self): """Test a user can't see another user pages.""" email1 = '*****@*****.**' name1 = 'User 1' email2 = '*****@*****.**' name2 = 'User 2' # Login as one user and view 'unit' and other pages, which are not # cached. actions.login(email1) actions.register(self, name1) actions.Permissions.assert_enrolled(self) response = actions.view_unit(self) assert_contains(email1, response.body) actions.logout() # Login as another user and check that 'unit' and other pages show # the correct new email. actions.login(email2) actions.register(self, name2) actions.Permissions.assert_enrolled(self) response = actions.view_unit(self) assert_contains(email2, response.body) actions.logout()
def setUp(self): super(AccessDraftsTestCase, self).setUp() actions.login(self.ADMIN_EMAIL, is_admin=True) self.base = '/' + self.COURSE_NAME self.context = actions.simple_add_course(self.COURSE_NAME, self.ADMIN_EMAIL, 'Access Draft Testing') self.course = courses.Course(None, self.context) self.old_namespace = namespace_manager.get_namespace() namespace_manager.set_namespace('ns_%s' % self.COURSE_NAME) role_dto = models.RoleDTO( None, { 'name': self.ROLE, 'users': [self.USER_EMAIL], 'permissions': { courses_module.custom_module.name: [courses_module.SEE_DRAFTS_PERMISSION] } }) models.RoleDAO.save(role_dto) actions.logout()
def test_independence_of_draft_reviews(self): """Test that draft reviews do not interfere with each other.""" email1 = '*****@*****.**' name1 = 'Student 1' submission1 = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True }, ]) payload1 = { 'answers': submission1, 'assessment_type': LEGACY_REVIEW_UNIT_ID } email2 = '*****@*****.**' name2 = 'Student 2' submission2 = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S2-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True }, ]) payload2 = { 'answers': submission2, 'assessment_type': LEGACY_REVIEW_UNIT_ID } email3 = '*****@*****.**' name3 = 'Student 3' submission3 = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S3-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True }, ]) payload3 = { 'answers': submission3, 'assessment_type': LEGACY_REVIEW_UNIT_ID } # Student 1 submits the assignment. actions.login(email1) actions.register(self, name1) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload1) actions.logout() # Student 2 logs in and submits the assignment. actions.login(email2) actions.register(self, name2) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload2) actions.logout() # Student 3 logs in and submits the assignment. actions.login(email3) actions.register(self, name3) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload3) actions.logout() # Student 1 logs in and requests two assignments to review. actions.login(email1) response = self.get('/reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('Assignment to review', response.body) assert_contains('not-S1', response.body) review_step_key_1_for_someone = get_review_step_key(response) response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('Assignment to review', response.body) assert_contains('not-S1', response.body) review_step_key_1_for_someone_else = get_review_step_key(response) self.assertNotEqual(review_step_key_1_for_someone, review_step_key_1_for_someone_else) # Student 1 submits two draft reviews. response = actions.submit_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone, get_review_payload('R1forFirst', is_draft=True)) assert_contains('Your review has been saved.', response.body) response = actions.submit_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone_else, get_review_payload('R1forSecond', is_draft=True)) assert_contains('Your review has been saved.', response.body) # The two draft reviews should still be different when subsequently # accessed. response = self.get( 'review?unit=%s&key=%s' % (LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone)) assert_contains('R1forFirst', response.body) response = self.get( 'review?unit=%s&key=%s' % (LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone_else)) assert_contains('R1forSecond', response.body) # Student 1 logs out. actions.logout()
def test_peer_review_analytics(self): """Test analytics page on course dashboard.""" student1 = '*****@*****.**' name1 = 'Test Student 1' student2 = '*****@*****.**' name2 = 'Test Student 2' peer = {'assessment_type': 'ReviewAssessmentExample'} # Student 1 submits a peer review assessment. actions.login(student1) actions.register(self, name1) actions.submit_assessment(self, 'ReviewAssessmentExample', peer) actions.logout() # Student 2 submits the same peer review assessment. actions.login(student2) actions.register(self, name2) actions.submit_assessment(self, 'ReviewAssessmentExample', peer) actions.logout() email = '*****@*****.**' # The admin looks at the analytics page on the dashboard. actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics&tab=peer_review') assert_contains( 'Google > Dashboard > Analytics > Peer Review', response.body) assert_contains('have not been calculated yet', response.body) response = response.forms['gcb-generate-analytics-data'].submit( ).follow() assert len(self.taskq.GetTasks('default')) == 1 assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get(response.request.url) assert_contains('were last updated at', response.body) assert_contains('Peer Review', response.body) assert_contains('Sample peer review assignment', response.body) # JSON code for the completion statistics. assert_contains('"[{\\"stats\\": [2]', response.body) actions.logout() # Student2 requests a review. actions.login(student2) response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) review_step_key_2_for_1 = get_review_step_key(response) assert_contains('Assignment to review', response.body) # Student2 submits the review. response = actions.submit_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, get_review_payload('R2for1')) assert_contains('Your review has been submitted successfully', response.body) actions.logout() actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics&tab=peer_review') assert_contains( 'Google > Dashboard > Analytics > Peer Review', response.body) response = response.forms['gcb-generate-analytics-data'].submit( ).follow() self.execute_all_deferred_tasks() response = self.get(response.request.url) assert_contains('Peer Review', response.body) # JSON code for the completion statistics. assert_contains('"[{\\"stats\\": [1, 1]', response.body) actions.logout()
def test_reviewer_cannot_impersonate_another_reviewer(self): """Test that one reviewer cannot use another's review step key.""" email1 = '*****@*****.**' name1 = 'Student 1' submission1 = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True }, ]) payload1 = { 'answers': submission1, 'assessment_type': LEGACY_REVIEW_UNIT_ID } email2 = '*****@*****.**' name2 = 'Student 2' submission2 = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S2-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True }, ]) payload2 = { 'answers': submission2, 'assessment_type': LEGACY_REVIEW_UNIT_ID } email3 = '*****@*****.**' name3 = 'Student 3' submission3 = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S3-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True }, ]) payload3 = { 'answers': submission3, 'assessment_type': LEGACY_REVIEW_UNIT_ID } # Student 1 submits the assignment. actions.login(email1) actions.register(self, name1) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload1) actions.logout() # Student 2 logs in and submits the assignment. actions.login(email2) actions.register(self, name2) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload2) # Student 2 requests a review, and is given Student 1's assignment. response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) review_step_key_2_for_1 = get_review_step_key(response) assert_contains('S1-1', response.body) actions.logout() # Student 3 logs in, and submits the assignment. actions.login(email3) actions.register(self, name3) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload3) # Student 3 tries to view Student 1's assignment using Student 2's # review step key, but is not allowed to. response = actions.view_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, expected_status_code=404) # Student 3 logs out. actions.logout()
def test_draft_review_behaviour(self): """Test correctness of draft review visibility.""" email1 = '*****@*****.**' name1 = 'Student 1' submission1 = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True }, ]) payload1 = { 'answers': submission1, 'assessment_type': LEGACY_REVIEW_UNIT_ID } email2 = '*****@*****.**' name2 = 'Student 2' submission2 = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S2-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True }, ]) payload2 = { 'answers': submission2, 'assessment_type': LEGACY_REVIEW_UNIT_ID } email3 = '*****@*****.**' name3 = 'Student 3' submission3 = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'S3-1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True }, ]) payload3 = { 'answers': submission3, 'assessment_type': LEGACY_REVIEW_UNIT_ID } # Student 1 submits the assignment. actions.login(email1) actions.register(self, name1) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload1) actions.logout() # Student 2 logs in and submits the assignment. actions.login(email2) actions.register(self, name2) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload2) # Student 2 requests a review, and is given Student 1's assignment. response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) review_step_key_2_for_1 = get_review_step_key(response) assert_contains('S1-1', response.body) # Student 2 saves her review as a draft. review_2_for_1_payload = get_review_payload('R2for1', is_draft=True) response = actions.submit_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, review_2_for_1_payload) assert_contains('Your review has been saved.', response.body) response = self.get('reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('(Draft)', response.body) # Student 2's draft is still changeable. response = actions.view_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1) assert_contains('Submit Review', response.body) response = actions.submit_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, review_2_for_1_payload) assert_contains('Your review has been saved.', response.body) # Student 2 logs out. actions.logout() # Student 3 submits the assignment. actions.login(email3) actions.register(self, name3) response = actions.submit_assessment(self, LEGACY_REVIEW_UNIT_ID, payload3) actions.logout() # Student 1 logs in and requests two assignments to review. actions.login(email1) response = self.get('/reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) assert_contains('Assignment to review', response.body) assert_contains('not-S1', response.body) review_step_key_1_for_someone = get_review_step_key(response) response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) assert_contains('Assignment to review', response.body) assert_contains('not-S1', response.body) review_step_key_1_for_someone_else = get_review_step_key(response) response = self.get('reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('disabled="true"', response.body) # Student 1 submits both reviews, fulfilling his quota. review_1_for_other_payload = get_review_payload('R1for') response = actions.submit_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone, review_1_for_other_payload) assert_contains('Your review has been submitted successfully', response.body) response = actions.submit_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone_else, review_1_for_other_payload) assert_contains('Your review has been submitted successfully', response.body) response = self.get('/reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) assert_contains('(Completed)', response.body) assert_does_not_contain('(Draft)', response.body) # Although Student 1 has submitted 2 reviews, he cannot view Student # 2's review because it is still in Draft status. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('You have not received any peer reviews yet.', response.body) assert_does_not_contain('R2for1', response.body) # Student 1 logs out. actions.logout() # Student 2 submits her review for Student 1's assignment. actions.login(email2) response = self.get('review?unit=%s&key=%s' % (LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1)) assert_does_not_contain('Submitted review', response.body) response = actions.submit_review(self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, get_review_payload('R2for1')) assert_contains('Your review has been submitted successfully', response.body) # Her review is now read-only. response = self.get('review?unit=%s&key=%s' % (LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1)) assert_contains('Submitted review', response.body) assert_contains('R2for1', response.body) # Student 2 logs out. actions.logout() # Now Student 1 can see the review he has received from Student 2. actions.login(email1) response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('R2for1', response.body)
def test_submit_assignment(self): """Test submission of peer-reviewed assignments.""" # Override course.yaml settings by patching app_context. get_environ_old = sites.ApplicationContext.get_environ def get_environ_new(self): environ = get_environ_old(self) environ['course']['browsable'] = False return environ sites.ApplicationContext.get_environ = get_environ_new email = '*****@*****.**' name = 'Test Peer Reviewed Assignment Submission' submission = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'First answer to Q1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'First answer to Q3', 'correct': True }, ]) second_submission = transforms.dumps([ { 'index': 0, 'type': 'regex', 'value': 'Second answer to Q1', 'correct': True }, { 'index': 1, 'type': 'choices', 'value': 3, 'correct': False }, { 'index': 2, 'type': 'regex', 'value': 'Second answer to Q3', 'correct': True }, ]) # Check that the sample peer-review assignment shows up in the preview # page. response = actions.view_preview(self) assert_contains('Sample peer review assignment', response.body) assert_does_not_contain('Review peer assignments', response.body) actions.login(email) actions.register(self, name) # Check that the sample peer-review assignment shows up in the course # page and that it can be visited. response = actions.view_course(self) assert_contains('Sample peer review assignment', response.body) assert_contains('Review peer assignments', response.body) assert_contains( '<a href="assessment?name=%s">' % LEGACY_REVIEW_UNIT_ID, response.body) assert_contains('<span> Review peer assignments </span>', response.body, collapse_whitespace=True) assert_does_not_contain('<a href="reviewdashboard', response.body, collapse_whitespace=True) # Check that the progress circle for this assignment is unfilled. assert_contains('progress-notstarted-%s' % LEGACY_REVIEW_UNIT_ID, response.body) assert_does_not_contain( 'progress-completed-%s' % LEGACY_REVIEW_UNIT_ID, response.body) # Try to access an invalid assignment. response = self.get('assessment?name=FakeAssessment', expect_errors=True) assert_equals(response.status_int, 404) # The student should not be able to see others' reviews because he/she # has not submitted an assignment yet. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) assert_does_not_contain('Submitted assignment', response.body) assert_contains('Due date for this assignment', response.body) assert_does_not_contain('Reviews received', response.body) # The student should not be able to access the review dashboard because # he/she has not submitted the assignment yet. response = self.get('reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID, expect_errors=True) assert_contains('You must submit the assignment for', response.body) # The student submits the assignment. response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, { 'answers': submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID }) assert_contains('Thank you for completing this assignment', response.body) assert_contains('Review peer assignments', response.body) # The student views the submitted assignment, which has become readonly. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) assert_contains('First answer to Q1', response.body) assert_contains('Submitted assignment', response.body) # The student tries to re-submit the same assignment. This should fail. response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, { 'answers': second_submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID }, presubmit_checks=False) assert_contains('You have already submitted this assignment.', response.body) assert_contains('Review peer assignments', response.body) # The student views the submitted assignment. The new answers have not # been saved. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) assert_contains('First answer to Q1', response.body) assert_does_not_contain('Second answer to Q1', response.body) # The student checks the course page and sees that the progress # circle for this assignment has been filled, and that the 'Review # peer assignments' link is now available. response = actions.view_course(self) assert_contains('progress-completed-%s' % LEGACY_REVIEW_UNIT_ID, response.body) assert_does_not_contain('<span> Review peer assignments </span>', response.body, collapse_whitespace=True) assert_contains('<a href="reviewdashboard?unit=%s">' % LEGACY_REVIEW_UNIT_ID, response.body, collapse_whitespace=True) # The student should also be able to now view the review dashboard. response = self.get('reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) assert_contains('Assignments for your review', response.body) assert_contains('Review a new assignment', response.body) actions.logout() # Clean up app_context. sites.ApplicationContext.get_environ = get_environ_old
def test_submit_assignment(self): """Test submission of peer-reviewed assignments.""" # Override course.yaml settings by patching app_context. get_environ_old = sites.ApplicationContext.get_environ def get_environ_new(self): environ = get_environ_old(self) environ['course']['browsable'] = False return environ sites.ApplicationContext.get_environ = get_environ_new email = '*****@*****.**' name = 'Test Peer Reviewed Assignment Submission' submission = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'First answer to Q1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'First answer to Q3', 'correct': True}, ]) second_submission = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'Second answer to Q1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'Second answer to Q3', 'correct': True}, ]) # Check that the sample peer-review assignment shows up in the preview # page. response = actions.view_preview(self) assert_contains('Sample peer review assignment', response.body) assert_does_not_contain('Review peer assignments', response.body) actions.login(email) actions.register(self, name) # Check that the sample peer-review assignment shows up in the course # page and that it can be visited. response = actions.view_course(self) assert_contains('Sample peer review assignment', response.body) assert_contains('Review peer assignments', response.body) assert_contains( '<a href="assessment?name=%s">' % LEGACY_REVIEW_UNIT_ID, response.body) assert_contains('<span> Review peer assignments </span>', response.body, collapse_whitespace=True) assert_does_not_contain('<a href="reviewdashboard', response.body, collapse_whitespace=True) # Check that the progress circle for this assignment is unfilled. assert_contains( 'progress-notstarted-%s' % LEGACY_REVIEW_UNIT_ID, response.body) assert_does_not_contain( 'progress-completed-%s' % LEGACY_REVIEW_UNIT_ID, response.body) # Try to access an invalid assignment. response = self.get( 'assessment?name=FakeAssessment', expect_errors=True) assert_equals(response.status_int, 404) # The student should not be able to see others' reviews because he/she # has not submitted an assignment yet. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) assert_does_not_contain('Submitted assignment', response.body) assert_contains('Due date for this assignment', response.body) assert_does_not_contain('Reviews received', response.body) # The student should not be able to access the review dashboard because # he/she has not submitted the assignment yet. response = self.get( 'reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID, expect_errors=True) assert_contains('You must submit the assignment for', response.body) # The student submits the assignment. response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, {'answers': submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID} ) assert_contains( 'Thank you for completing this assignment', response.body) assert_contains('Review peer assignments', response.body) # The student views the submitted assignment, which has become readonly. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) assert_contains('First answer to Q1', response.body) assert_contains('Submitted assignment', response.body) # The student tries to re-submit the same assignment. This should fail. response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, {'answers': second_submission, 'assessment_type': LEGACY_REVIEW_UNIT_ID}, presubmit_checks=False ) assert_contains( 'You have already submitted this assignment.', response.body) assert_contains('Review peer assignments', response.body) # The student views the submitted assignment. The new answers have not # been saved. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) assert_contains('First answer to Q1', response.body) assert_does_not_contain('Second answer to Q1', response.body) # The student checks the course page and sees that the progress # circle for this assignment has been filled, and that the 'Review # peer assignments' link is now available. response = actions.view_course(self) assert_contains( 'progress-completed-%s' % LEGACY_REVIEW_UNIT_ID, response.body) assert_does_not_contain( '<span> Review peer assignments </span>', response.body, collapse_whitespace=True) assert_contains( '<a href="reviewdashboard?unit=%s">' % LEGACY_REVIEW_UNIT_ID, response.body, collapse_whitespace=True) # The student should also be able to now view the review dashboard. response = self.get('reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) assert_contains('Assignments for your review', response.body) assert_contains('Review a new assignment', response.body) actions.logout() # Clean up app_context. sites.ApplicationContext.get_environ = get_environ_old
def logout_page(): logout() return redirect(url_for('root'))
def test_independence_of_draft_reviews(self): """Test that draft reviews do not interfere with each other.""" email1 = '*****@*****.**' name1 = 'Student 1' submission1 = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True}, ]) payload1 = { 'answers': submission1, 'assessment_type': LEGACY_REVIEW_UNIT_ID} email2 = '*****@*****.**' name2 = 'Student 2' submission2 = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S2-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True}, ]) payload2 = { 'answers': submission2, 'assessment_type': LEGACY_REVIEW_UNIT_ID} email3 = '*****@*****.**' name3 = 'Student 3' submission3 = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S3-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True}, ]) payload3 = { 'answers': submission3, 'assessment_type': LEGACY_REVIEW_UNIT_ID} # Student 1 submits the assignment. actions.login(email1) actions.register(self, name1) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload1) actions.logout() # Student 2 logs in and submits the assignment. actions.login(email2) actions.register(self, name2) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload2) actions.logout() # Student 3 logs in and submits the assignment. actions.login(email3) actions.register(self, name3) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload3) actions.logout() # Student 1 logs in and requests two assignments to review. actions.login(email1) response = self.get('/reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('Assignment to review', response.body) assert_contains('not-S1', response.body) review_step_key_1_for_someone = get_review_step_key(response) response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('Assignment to review', response.body) assert_contains('not-S1', response.body) review_step_key_1_for_someone_else = get_review_step_key(response) self.assertNotEqual( review_step_key_1_for_someone, review_step_key_1_for_someone_else) # Student 1 submits two draft reviews. response = actions.submit_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone, get_review_payload('R1forFirst', is_draft=True)) assert_contains('Your review has been saved.', response.body) response = actions.submit_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone_else, get_review_payload('R1forSecond', is_draft=True)) assert_contains('Your review has been saved.', response.body) # The two draft reviews should still be different when subsequently # accessed. response = self.get('review?unit=%s&key=%s' % ( LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone)) assert_contains('R1forFirst', response.body) response = self.get('review?unit=%s&key=%s' % ( LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone_else)) assert_contains('R1forSecond', response.body) # Student 1 logs out. actions.logout()
def test_draft_review_behaviour(self): """Test correctness of draft review visibility.""" email1 = '*****@*****.**' name1 = 'Student 1' submission1 = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True}, ]) payload1 = { 'answers': submission1, 'assessment_type': LEGACY_REVIEW_UNIT_ID} email2 = '*****@*****.**' name2 = 'Student 2' submission2 = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S2-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True}, ]) payload2 = { 'answers': submission2, 'assessment_type': LEGACY_REVIEW_UNIT_ID} email3 = '*****@*****.**' name3 = 'Student 3' submission3 = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S3-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True}, ]) payload3 = { 'answers': submission3, 'assessment_type': LEGACY_REVIEW_UNIT_ID} # Student 1 submits the assignment. actions.login(email1) actions.register(self, name1) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload1) actions.logout() # Student 2 logs in and submits the assignment. actions.login(email2) actions.register(self, name2) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload2) # Student 2 requests a review, and is given Student 1's assignment. response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) review_step_key_2_for_1 = get_review_step_key(response) assert_contains('S1-1', response.body) # Student 2 saves her review as a draft. review_2_for_1_payload = get_review_payload( 'R2for1', is_draft=True) response = actions.submit_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, review_2_for_1_payload) assert_contains('Your review has been saved.', response.body) response = self.get('reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('(Draft)', response.body) # Student 2's draft is still changeable. response = actions.view_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1) assert_contains('Submit Review', response.body) response = actions.submit_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, review_2_for_1_payload) assert_contains('Your review has been saved.', response.body) # Student 2 logs out. actions.logout() # Student 3 submits the assignment. actions.login(email3) actions.register(self, name3) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload3) actions.logout() # Student 1 logs in and requests two assignments to review. actions.login(email1) response = self.get('/reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) assert_contains('Assignment to review', response.body) assert_contains('not-S1', response.body) review_step_key_1_for_someone = get_review_step_key(response) response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) assert_contains('Assignment to review', response.body) assert_contains('not-S1', response.body) review_step_key_1_for_someone_else = get_review_step_key(response) response = self.get('reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('disabled="true"', response.body) # Student 1 submits both reviews, fulfilling his quota. review_1_for_other_payload = get_review_payload('R1for') response = actions.submit_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone, review_1_for_other_payload) assert_contains( 'Your review has been submitted successfully', response.body) response = actions.submit_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_1_for_someone_else, review_1_for_other_payload) assert_contains( 'Your review has been submitted successfully', response.body) response = self.get('/reviewdashboard?unit=%s' % LEGACY_REVIEW_UNIT_ID) assert_contains('(Completed)', response.body) assert_does_not_contain('(Draft)', response.body) # Although Student 1 has submitted 2 reviews, he cannot view Student # 2's review because it is still in Draft status. response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains( 'You have not received any peer reviews yet.', response.body) assert_does_not_contain('R2for1', response.body) # Student 1 logs out. actions.logout() # Student 2 submits her review for Student 1's assignment. actions.login(email2) response = self.get('review?unit=%s&key=%s' % ( LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1)) assert_does_not_contain('Submitted review', response.body) response = actions.submit_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, get_review_payload('R2for1')) assert_contains( 'Your review has been submitted successfully', response.body) # Her review is now read-only. response = self.get('review?unit=%s&key=%s' % ( LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1)) assert_contains('Submitted review', response.body) assert_contains('R2for1', response.body) # Student 2 logs out. actions.logout() # Now Student 1 can see the review he has received from Student 2. actions.login(email1) response = self.get('assessment?name=%s' % LEGACY_REVIEW_UNIT_ID) assert_equals(response.status_int, 200) assert_contains('R2for1', response.body)
def test_peer_review_analytics(self): """Test analytics page on course dashboard.""" student1 = '*****@*****.**' name1 = 'Test Student 1' student2 = '*****@*****.**' name2 = 'Test Student 2' peer = {'assessment_type': 'ReviewAssessmentExample'} # Student 1 submits a peer review assessment. actions.login(student1) actions.register(self, name1) actions.submit_assessment(self, 'ReviewAssessmentExample', peer) actions.logout() # Student 2 submits the same peer review assessment. actions.login(student2) actions.register(self, name2) actions.submit_assessment(self, 'ReviewAssessmentExample', peer) actions.logout() email = '*****@*****.**' # The admin looks at the analytics page on the dashboard. actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics') assert_contains( 'Google ><a href="%s"> Dashboard </a>> Analytics' % self.canonicalize('dashboard'), response.body) assert_contains('have not been calculated yet', response.body) compute_form = response.forms['gcb-compute-student-stats'] response = self.submit(compute_form) assert_equals(response.status_int, 302) assert len(self.taskq.GetTasks('default')) == 5 response = self.get('dashboard?action=analytics') assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get('dashboard?action=analytics') assert_contains('were last updated at', response.body) assert_contains('currently enrolled: 2', response.body) assert_contains('total: 2', response.body) assert_contains('Peer Review Statistics', response.body) assert_contains('Sample peer review assignment', response.body) # JSON code for the completion statistics. assert_contains('"[{\\"stats\\": [2]', response.body) actions.logout() # Student2 requests a review. actions.login(student2) response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) review_step_key_2_for_1 = get_review_step_key(response) assert_contains('Assignment to review', response.body) # Student2 submits the review. response = actions.submit_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, get_review_payload('R2for1')) assert_contains( 'Your review has been submitted successfully', response.body) actions.logout() actions.login(email, is_admin=True) response = self.get('dashboard?action=analytics') assert_contains( 'Google ><a href="%s"> Dashboard </a>> Analytics' % self.canonicalize('dashboard'), response.body) compute_form = response.forms['gcb-compute-student-stats'] response = self.submit(compute_form) self.execute_all_deferred_tasks() response = self.get('dashboard?action=analytics') assert_contains('Peer Review Statistics', response.body) # JSON code for the completion statistics. assert_contains('"[{\\"stats\\": [1, 1]', response.body) actions.logout()
def test_reviewer_cannot_impersonate_another_reviewer(self): """Test that one reviewer cannot use another's review step key.""" email1 = '*****@*****.**' name1 = 'Student 1' submission1 = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S1-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'is-S1', 'correct': True}, ]) payload1 = { 'answers': submission1, 'assessment_type': LEGACY_REVIEW_UNIT_ID} email2 = '*****@*****.**' name2 = 'Student 2' submission2 = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S2-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True}, ]) payload2 = { 'answers': submission2, 'assessment_type': LEGACY_REVIEW_UNIT_ID} email3 = '*****@*****.**' name3 = 'Student 3' submission3 = transforms.dumps([ {'index': 0, 'type': 'regex', 'value': 'S3-1', 'correct': True}, {'index': 1, 'type': 'choices', 'value': 3, 'correct': False}, {'index': 2, 'type': 'regex', 'value': 'not-S1', 'correct': True}, ]) payload3 = { 'answers': submission3, 'assessment_type': LEGACY_REVIEW_UNIT_ID} # Student 1 submits the assignment. actions.login(email1) actions.register(self, name1) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload1) actions.logout() # Student 2 logs in and submits the assignment. actions.login(email2) actions.register(self, name2) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload2) # Student 2 requests a review, and is given Student 1's assignment. response = actions.request_new_review(self, LEGACY_REVIEW_UNIT_ID) review_step_key_2_for_1 = get_review_step_key(response) assert_contains('S1-1', response.body) actions.logout() # Student 3 logs in, and submits the assignment. actions.login(email3) actions.register(self, name3) response = actions.submit_assessment( self, LEGACY_REVIEW_UNIT_ID, payload3) # Student 3 tries to view Student 1's assignment using Student 2's # review step key, but is not allowed to. response = actions.view_review( self, LEGACY_REVIEW_UNIT_ID, review_step_key_2_for_1, expected_status_code=404) # Student 3 logs out. actions.logout()
def test_dashboard(self): """Test course dashboard.""" email = '*****@*****.**' name = 'Test Dashboard' # Non-admin does't have access. actions.login(email) response = self.get('dashboard') assert_equals(response.status_int, 302) actions.register(self, name) assert_equals(response.status_int, 302) actions.logout() # Admin has access. actions.login(email, True) response = self.get('dashboard') assert_contains('Google > Dashboard > Outline', response.body) # Tests outline view. response = self.get('dashboard') assert_contains('Unit 3 - Advanced techniques', response.body) # Test assets view. response = self.get('dashboard?action=assets') assert_contains('Google > Dashboard > Assets', response.body) assert_contains('data/lesson.csv', response.body) assert_contains('assets/css/main.css', response.body) assert_contains('assets/img/Image1.5.png', response.body) assert_contains('assets/js/activity-3.2.js', response.body) # Test settings view. response = self.get('dashboard?action=settings') assert_contains( 'Google > Dashboard > Settings', response.body) assert_contains('course.yaml', response.body) assert_contains('title: \'Power Searching with Google\'', response.body) assert_contains('locale: \'en_US\'', response.body) # Tests student statistics view. response = self.get('dashboard?action=students') assert_contains( 'Google > Dashboard > Students', response.body) assert_contains('have not been calculated yet', response.body) compute_form = response.forms['gcb-compute-student-stats'] response = self.submit(compute_form) assert_equals(response.status_int, 302) assert len(self.taskq.GetTasks('default')) == 1 response = self.get('dashboard?action=students') assert_contains('is running', response.body) self.execute_all_deferred_tasks() response = self.get('dashboard?action=students') assert_contains('were last updated on', response.body) assert_contains('currently enrolled: 1', response.body) assert_contains('total: 1', response.body) # Tests assessment statistics. old_namespace = namespace_manager.get_namespace() namespace_manager.set_namespace(self.namespace) try: for i in range(5): student = models.Student(key_name='key-%s' % i) student.is_enrolled = True student.scores = json.dumps({'test-assessment': i}) student.put() finally: namespace_manager.set_namespace(old_namespace) response = self.get('dashboard?action=students') compute_form = response.forms['gcb-compute-student-stats'] response = self.submit(compute_form) self.execute_all_deferred_tasks() response = self.get('dashboard?action=students') assert_contains('currently enrolled: 6', response.body) assert_contains( 'test-assessment: completed 5, average score 2.0', response.body)