From 78790efdd8b2f33eb43d52dec107e855a4221baa Mon Sep 17 00:00:00 2001 From: Awais Jibran Date: Fri, 23 Dec 2016 15:23:02 +0500 Subject: [PATCH] Fix rescore TNL-6199 --- .../instructor_task/tasks_helper.py | 4 +- .../instructor_task/tests/test_tasks.py | 104 +++++++++++++----- 2 files changed, 80 insertions(+), 28 deletions(-) diff --git a/lms/djangoapps/instructor_task/tasks_helper.py b/lms/djangoapps/instructor_task/tasks_helper.py index 95c8b76d1f..1435db9b9b 100644 --- a/lms/djangoapps/instructor_task/tasks_helper.py +++ b/lms/djangoapps/instructor_task/tasks_helper.py @@ -514,8 +514,8 @@ def rescore_problem_module_state(xmodule_instance_args, module_descriptor, stude loc=usage_key, student=student ) - TASK_LOG.debug(msg) - raise UpdateProblemModuleStateError(msg) + TASK_LOG.warning(msg) + return UPDATE_STATUS_FAILED if not hasattr(instance, 'rescore_problem'): # This should also not happen, since it should be already checked in the caller, diff --git a/lms/djangoapps/instructor_task/tests/test_tasks.py b/lms/djangoapps/instructor_task/tests/test_tasks.py index bd82c4df22..b4e3c4d399 100644 --- a/lms/djangoapps/instructor_task/tests/test_tasks.py +++ b/lms/djangoapps/instructor_task/tests/test_tasks.py @@ -222,6 +222,23 @@ class TestInstructorTasks(InstructorTaskModuleTestCase): class TestRescoreInstructorTask(TestInstructorTasks): """Tests problem-rescoring instructor task.""" + def assert_task_output(self, output, **expected_output): + """ + Check & compare output of the task + """ + self.assertEqual(output.get('total'), expected_output.get('total')) + self.assertEqual(output.get('attempted'), expected_output.get('attempted')) + self.assertEqual(output.get('succeeded'), expected_output.get('succeeded')) + self.assertEqual(output.get('skipped'), expected_output.get('skipped')) + self.assertEqual(output.get('failed'), expected_output.get('failed')) + self.assertEqual(output.get('action_name'), expected_output.get('action_name')) + self.assertGreater(output.get('duration_ms'), expected_output.get('duration_ms', 0)) + + def get_task_output(self, task_id): + """Get and load instructor task output""" + entry = InstructorTask.objects.get(id=task_id) + return json.loads(entry.task_output) + def test_rescore_missing_current_task(self): self._test_missing_current_task(rescore_problem) @@ -261,7 +278,32 @@ class TestRescoreInstructorTask(TestInstructorTasks): self.assertEquals(output['message'], "Specified problem does not support rescoring.") self.assertGreater(len(output['traceback']), 0) + def test_rescoring_unaccessable(self): + """ + Tests rescores a problem in a course, for all students fails if user has answered a + problem to which user does not have access to. + """ + input_state = json.dumps({'done': True}) + num_students = 1 + self._create_students_with_state(num_students, input_state) + task_entry = self._create_input_entry() + with patch('lms.djangoapps.instructor_task.tasks_helper.get_module_for_descriptor_internal', return_value=None): + self._run_task_with_mock_celery(rescore_problem, task_entry.id, task_entry.task_id) + + self.assert_task_output( + output=self.get_task_output(task_entry.id), + total=num_students, + attempted=num_students, + succeeded=0, + skipped=0, + failed=num_students, + action_name='rescored' + ) + def test_rescoring_success(self): + """ + Tests rescores a problem in a course, for all students succeeds. + """ input_state = json.dumps({'done': True}) num_students = 10 self._create_students_with_state(num_students, input_state) @@ -277,17 +319,21 @@ class TestRescoreInstructorTask(TestInstructorTasks): with patch('lms.djangoapps.instructor_task.tasks_helper.get_module_for_descriptor_internal') as mock_get_module: mock_get_module.return_value = mock_instance self._run_task_with_mock_celery(rescore_problem, task_entry.id, task_entry.task_id) - # check return value - entry = InstructorTask.objects.get(id=task_entry.id) - output = json.loads(entry.task_output) - self.assertEquals(output.get('attempted'), num_students) - self.assertEquals(output.get('succeeded'), num_students) - self.assertEquals(output.get('total'), num_students) - self.assertEquals(output.get('action_name'), 'rescored') - self.assertGreater(output.get('duration_ms'), 0) + + self.assert_task_output( + output=self.get_task_output(task_entry.id), + total=num_students, + attempted=num_students, + succeeded=num_students, + skipped=0, + failed=0, + action_name='rescored' + ) def test_rescoring_bad_result(self): - # Confirm that rescoring does not succeed if "success" key is not an expected value. + """ + Tests and confirm that rescoring does not succeed if "success" key is not an expected value. + """ input_state = json.dumps({'done': True}) num_students = 10 self._create_students_with_state(num_students, input_state) @@ -297,17 +343,21 @@ class TestRescoreInstructorTask(TestInstructorTasks): with patch('lms.djangoapps.instructor_task.tasks_helper.get_module_for_descriptor_internal') as mock_get_module: mock_get_module.return_value = mock_instance self._run_task_with_mock_celery(rescore_problem, task_entry.id, task_entry.task_id) - # check return value - entry = InstructorTask.objects.get(id=task_entry.id) - output = json.loads(entry.task_output) - self.assertEquals(output.get('attempted'), num_students) - self.assertEquals(output.get('succeeded'), 0) - self.assertEquals(output.get('total'), num_students) - self.assertEquals(output.get('action_name'), 'rescored') - self.assertGreater(output.get('duration_ms'), 0) + + self.assert_task_output( + output=self.get_task_output(task_entry.id), + total=num_students, + attempted=num_students, + succeeded=0, + skipped=0, + failed=num_students, + action_name='rescored' + ) def test_rescoring_missing_result(self): - # Confirm that rescoring does not succeed if "success" key is not returned. + """ + Tests and confirm that rescoring does not succeed if "success" key is not returned. + """ input_state = json.dumps({'done': True}) num_students = 10 self._create_students_with_state(num_students, input_state) @@ -317,14 +367,16 @@ class TestRescoreInstructorTask(TestInstructorTasks): with patch('lms.djangoapps.instructor_task.tasks_helper.get_module_for_descriptor_internal') as mock_get_module: mock_get_module.return_value = mock_instance self._run_task_with_mock_celery(rescore_problem, task_entry.id, task_entry.task_id) - # check return value - entry = InstructorTask.objects.get(id=task_entry.id) - output = json.loads(entry.task_output) - self.assertEquals(output.get('attempted'), num_students) - self.assertEquals(output.get('succeeded'), 0) - self.assertEquals(output.get('total'), num_students) - self.assertEquals(output.get('action_name'), 'rescored') - self.assertGreater(output.get('duration_ms'), 0) + + self.assert_task_output( + output=self.get_task_output(task_entry.id), + total=num_students, + attempted=num_students, + succeeded=0, + skipped=0, + failed=num_students, + action_name='rescored' + ) @attr(shard=3)