def test_submit_nonrescorable_modules(self): # confirm that a rescore of an existent but unscorable module returns an exception # (Note that it is easier to test a scoreable but non-rescorable module in test_tasks, # where we are creating real modules.) problem_url = self.problem_section.location request = None with pytest.raises(NotImplementedError): submit_rescore_problem_for_student(request, problem_url, self.student) with pytest.raises(NotImplementedError): submit_rescore_problem_for_all_students(request, problem_url)
def test_submit_nonrescorable_modules(self): # confirm that a rescore of an existent but unscorable module returns an exception # (Note that it is easier to test a scoreable but non-rescorable module in test_tasks, # where we are creating real modules.) problem_url = self.problem_section.location request = None with self.assertRaises(NotImplementedError): submit_rescore_problem_for_student(request, problem_url, self.student) with self.assertRaises(NotImplementedError): submit_rescore_problem_for_all_students(request, problem_url)
def test_submit_nonexistent_modules(self): # confirm that a rescore of a non-existent module returns an exception problem_url = InstructorTaskModuleTestCase.problem_location("NonexistentProblem") request = None with self.assertRaises(ItemNotFoundError): submit_rescore_problem_for_student(request, problem_url, self.student) with self.assertRaises(ItemNotFoundError): submit_rescore_problem_for_all_students(request, problem_url) with self.assertRaises(ItemNotFoundError): submit_reset_problem_attempts_for_all_students(request, problem_url) with self.assertRaises(ItemNotFoundError): submit_delete_problem_state_for_all_students(request, problem_url)
def test_submit_nonexistent_modules(self): # confirm that a rescore of a non-existent module returns an exception problem_url = InstructorTaskModuleTestCase.problem_location("NonexistentProblem") request = None with pytest.raises(ItemNotFoundError): submit_rescore_problem_for_student(request, problem_url, self.student) with pytest.raises(ItemNotFoundError): submit_rescore_problem_for_all_students(request, problem_url) with pytest.raises(ItemNotFoundError): submit_reset_problem_attempts_for_all_students(request, problem_url) with pytest.raises(ItemNotFoundError): submit_delete_problem_state_for_all_students(request, problem_url)
def submit_rescore_one_student_answer(self, instructor, problem_url_name, student): """Submits the particular problem for rescoring for a particular student""" return submit_rescore_problem_for_student( self.create_task_request(instructor), InstructorTaskModuleTestCase.problem_location(problem_url_name), student)
def submit_rescore_one_student_answer(self, instructor, problem_url_name, student, only_if_higher=False): """Submits the particular problem for rescoring for a particular student""" return submit_rescore_problem_for_student( self.create_task_request(instructor), InstructorTaskModuleTestCase.problem_location(problem_url_name), student, only_if_higher, )
def test_rescoring_events(self, models_tracker, handlers_tracker, instructor_task_tracker): # submit answer self.submit_question_answer('p1', {'2_1': 'choice_choice_3'}) models_tracker.reset_mock() handlers_tracker.reset_mock() new_problem_xml = MultipleChoiceResponseXMLFactory().build_xml( question_text='The correct answer is Choice 3', choices=[False, False, False, True], choice_names=['choice_0', 'choice_1', 'choice_2', 'choice_3'] ) module_store = modulestore() with module_store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, self.course.id): self.problem.data = new_problem_xml module_store.update_item(self.problem, self.instructor.id) module_store.publish(self.problem.location, self.instructor.id) submit_rescore_problem_for_student( request=get_mock_request(self.instructor), usage_key=self.problem.location, student=self.student, only_if_higher=False ) # check logging to make sure id's are tracked correctly across # events event_transaction_id = instructor_task_tracker.emit.mock_calls[0][1][1]['event_transaction_id'] self.assertEqual( instructor_task_tracker.get_tracker().context.call_args[0], ('edx.grades.problem.rescored', {'course_id': unicode(self.course.id), 'org_id': unicode(self.course.org)}) ) # make sure the id is propagated throughout the event flow for call in models_tracker.emit.mock_calls: self.assertEqual(event_transaction_id, call[1][1]['event_transaction_id']) self.assertEqual(unicode(RESCORE_TYPE), call[1][1]['event_transaction_type']) # make sure the models calls have re-added the course id to the context for args in models_tracker.get_tracker().context.call_args_list: self.assertEqual( args[0][1], {'course_id': unicode(self.course.id), 'org_id': unicode(self.course.org)} ) handlers_tracker.assert_not_called() instructor_task_tracker.emit.assert_called_with( unicode(RESCORE_TYPE), { 'course_id': unicode(self.course.id), 'user_id': unicode(self.student.id), 'problem_id': unicode(self.problem.location), 'new_weighted_earned': 2, 'new_weighted_possible': 2, 'only_if_higher': False, 'instructor_id': unicode(self.instructor.id), 'event_transaction_id': event_transaction_id, 'event_transaction_type': unicode(RESCORE_TYPE), } ) course = modulestore().get_course(self.course.id, depth=0) models_tracker.emit.assert_called_with( u'edx.grades.course.grade_calculated', { 'course_version': unicode(course.course_version), 'percent_grade': 0.02, 'grading_policy_hash': u'ChVp0lHGQGCevD0t4njna/C44zQ=', 'user_id': unicode(self.student.id), 'letter_grade': u'', 'event_transaction_id': event_transaction_id, 'event_transaction_type': unicode(RESCORE_TYPE), 'course_id': unicode(self.course.id), 'course_edited_timestamp': unicode(course.subtree_edited_on), } ) instructor_task_tracker.reset_mock() models_tracker.reset_mock() handlers_tracker.reset_mock()
def test_rescoring_events(self, models_tracker, handlers_tracker, instructor_task_tracker): # submit answer self.submit_question_answer('p1', {'2_1': 'choice_choice_3'}) models_tracker.reset_mock() handlers_tracker.reset_mock() new_problem_xml = MultipleChoiceResponseXMLFactory().build_xml( question_text='The correct answer is Choice 3', choices=[False, False, False, True], choice_names=['choice_0', 'choice_1', 'choice_2', 'choice_3']) module_store = modulestore() with module_store.branch_setting( ModuleStoreEnum.Branch.draft_preferred, self.course.id): self.problem.data = new_problem_xml module_store.update_item(self.problem, self.instructor.id) module_store.publish(self.problem.location, self.instructor.id) submit_rescore_problem_for_student(request=get_mock_request( self.instructor), usage_key=self.problem.location, student=self.student, only_if_higher=False) # check logging to make sure id's are tracked correctly across # events event_transaction_id = instructor_task_tracker.emit.mock_calls[0][1][ 1]['event_transaction_id'] self.assertEqual( instructor_task_tracker.get_tracker().context.call_args[0], ('edx.grades.problem.rescored', { 'course_id': unicode(self.course.id), 'org_id': unicode(self.course.org) })) # make sure the id is propagated throughout the event flow for call in models_tracker.emit.mock_calls: self.assertEqual(event_transaction_id, call[1][1]['event_transaction_id']) self.assertEqual(unicode(RESCORE_TYPE), call[1][1]['event_transaction_type']) # make sure the models calls have re-added the course id to the context for args in models_tracker.get_tracker().context.call_args_list: self.assertEqual( args[0][1], { 'course_id': unicode(self.course.id), 'org_id': unicode(self.course.org) }) handlers_tracker.assert_not_called() instructor_task_tracker.emit.assert_called_with( unicode(RESCORE_TYPE), { 'course_id': unicode(self.course.id), 'user_id': unicode(self.student.id), 'problem_id': unicode(self.problem.location), 'new_weighted_earned': 2, 'new_weighted_possible': 2, 'only_if_higher': False, 'instructor_id': unicode(self.instructor.id), 'event_transaction_id': event_transaction_id, 'event_transaction_type': unicode(RESCORE_TYPE), }) course = modulestore().get_course(self.course.id, depth=0) models_tracker.emit.assert_called_with( u'edx.grades.course.grade_calculated', { 'course_version': unicode(course.course_version), 'percent_grade': 0.02, 'grading_policy_hash': u'ChVp0lHGQGCevD0t4njna/C44zQ=', 'user_id': unicode(self.student.id), 'letter_grade': u'', 'event_transaction_id': event_transaction_id, 'event_transaction_type': unicode(RESCORE_TYPE), 'course_id': unicode(self.course.id), 'course_edited_timestamp': unicode(course.subtree_edited_on), }) instructor_task_tracker.reset_mock() models_tracker.reset_mock() handlers_tracker.reset_mock()
def test_rescoring_events(self): self.submit_question_answer('p1', {'2_1': 'choice_choice_3'}) new_problem_xml = MultipleChoiceResponseXMLFactory().build_xml( question_text='The correct answer is Choice 3', choices=[False, False, False, True], choice_names=['choice_0', 'choice_1', 'choice_2', 'choice_3'] ) with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, self.course.id): self.problem.data = new_problem_xml self.store.update_item(self.problem, self.instructor.id) self.store.publish(self.problem.location, self.instructor.id) with patch('lms.djangoapps.grades.events.tracker') as events_tracker: submit_rescore_problem_for_student( request=get_mock_request(self.instructor), usage_key=self.problem.location, student=self.student, only_if_higher=False ) course = self.store.get_course(self.course.id, depth=0) # make sure the tracker's context is updated with course info for args in events_tracker.get_tracker().context.call_args_list: self.assertEqual( args[0][1], {'course_id': unicode(self.course.id), 'org_id': unicode(self.course.org)} ) event_transaction_id = events_tracker.emit.mock_calls[0][1][1]['event_transaction_id'] events_tracker.emit.assert_has_calls( [ mock_call( events.GRADES_RESCORE_EVENT_TYPE, { 'course_id': unicode(self.course.id), 'user_id': unicode(self.student.id), 'problem_id': unicode(self.problem.location), 'new_weighted_earned': 2, 'new_weighted_possible': 2, 'only_if_higher': False, 'instructor_id': unicode(self.instructor.id), 'event_transaction_id': event_transaction_id, 'event_transaction_type': events.GRADES_RESCORE_EVENT_TYPE, }, ), mock_call( events.COURSE_GRADE_CALCULATED, { 'course_version': unicode(course.course_version), 'percent_grade': 0.02, 'grading_policy_hash': u'ChVp0lHGQGCevD0t4njna/C44zQ=', 'user_id': unicode(self.student.id), 'letter_grade': u'', 'event_transaction_id': event_transaction_id, 'event_transaction_type': events.GRADES_RESCORE_EVENT_TYPE, 'course_id': unicode(self.course.id), 'course_edited_timestamp': unicode(course.subtree_edited_on), }, ), ], any_order=True, )
def test_rescoring_events(self): self.submit_question_answer('p1', {'2_1': 'choice_choice_3'}) new_problem_xml = MultipleChoiceResponseXMLFactory().build_xml( question_text='The correct answer is Choice 3', choices=[False, False, False, True], choice_names=['choice_0', 'choice_1', 'choice_2', 'choice_3']) with self.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, self.course.id): self.problem.data = new_problem_xml self.store.update_item(self.problem, self.instructor.id) self.store.publish(self.problem.location, self.instructor.id) with patch('lms.djangoapps.grades.events.tracker') as events_tracker: submit_rescore_problem_for_student(request=get_mock_request( self.instructor), usage_key=self.problem.location, student=self.student, only_if_higher=False) course = self.store.get_course(self.course.id, depth=0) # make sure the tracker's context is updated with course info for args in events_tracker.get_tracker().context.call_args_list: self.assertEqual( args[0][1], { 'course_id': six.text_type(self.course.id), 'org_id': six.text_type(self.course.org) }) event_transaction_id = events_tracker.emit.mock_calls[0][1][1][ 'event_transaction_id'] events_tracker.emit.assert_has_calls( [ mock_call( events.GRADES_RESCORE_EVENT_TYPE, { 'course_id': six.text_type(self.course.id), 'user_id': six.text_type(self.student.id), 'problem_id': six.text_type(self.problem.location), 'new_weighted_earned': 2, 'new_weighted_possible': 2, 'only_if_higher': False, 'instructor_id': six.text_type(self.instructor.id), 'event_transaction_id': event_transaction_id, 'event_transaction_type': events.GRADES_RESCORE_EVENT_TYPE, }, ), mock_call( events.COURSE_GRADE_CALCULATED, { 'course_version': six.text_type(course.course_version), 'percent_grade': 0.02, 'grading_policy_hash': u'ChVp0lHGQGCevD0t4njna/C44zQ=', 'user_id': six.text_type(self.student.id), 'letter_grade': u'', 'event_transaction_id': event_transaction_id, 'event_transaction_type': events.GRADES_RESCORE_EVENT_TYPE, 'course_id': six.text_type(self.course.id), 'course_edited_timestamp': six.text_type(course.subtree_edited_on), }, ), ], any_order=True, )