예제 #1
0
 def setUpClass(cls):
     super(GradeTestBase, cls).setUpClass()
     cls.course = CourseFactory.create()
     cls.chapter = ItemFactory.create(parent=cls.course,
                                      category="chapter",
                                      display_name="Test Chapter")
     cls.sequence = ItemFactory.create(parent=cls.chapter,
                                       category='sequential',
                                       display_name="Test Sequential 1",
                                       graded=True,
                                       format="Homework")
     cls.vertical = ItemFactory.create(parent=cls.sequence,
                                       category='vertical',
                                       display_name='Test Vertical 1')
     problem_xml = MultipleChoiceResponseXMLFactory().build_xml(
         question_text='The correct answer is Choice 3',
         choices=[False, False, True, False],
         choice_names=['choice_0', 'choice_1', 'choice_2', 'choice_3'])
     cls.problem = ItemFactory.create(parent=cls.vertical,
                                      category="problem",
                                      display_name="Test Problem",
                                      data=problem_xml)
예제 #2
0
 def users_and_problem_setup(self):
     self.chapter = ItemFactory.create(parent=self.course,
                                       category="chapter",
                                       display_name="Test Chapter")
     self.sequence = ItemFactory.create(parent=self.chapter,
                                        category='sequential',
                                        display_name="Test Sequential 1",
                                        graded=True,
                                        format="Homework")
     self.vertical = ItemFactory.create(parent=self.sequence,
                                        category='vertical',
                                        display_name='Test Vertical 1')
     problem_xml = MultipleChoiceResponseXMLFactory().build_xml(
         question_text='The correct answer is Choice 3',
         choices=[False, False, True, False],
         choice_names=['choice_0', 'choice_1', 'choice_2', 'choice_3'])
     self.problem = ItemFactory.create(parent=self.vertical,
                                       category="problem",
                                       display_name="Test Problem",
                                       data=problem_xml)
     self.user2 = UserFactory.create(username='******', password='******')
     self.user3 = UserFactory.create(username='******', password='******')
     self.request = get_mock_request(self.user)
예제 #3
0
    def create_course_data(cls):
        # pylint: disable=missing-docstring
        cls.invalid_course_id = 'foo/bar/baz'
        cls.course = CourseFactory.create(
            display_name='An Introduction to API Testing',
            raw_grader=cls.raw_grader)
        cls.course_id = unicode(cls.course.id)
        with cls.store.bulk_operations(cls.course.id, emit_signals=False):
            cls.sequential = ItemFactory.create(
                category="sequential",
                parent_location=cls.course.location,
                display_name="Lesson 1",
                format="Homework",
                graded=True)

            factory = MultipleChoiceResponseXMLFactory()
            args = {'choices': [False, True, False]}
            problem_xml = factory.build_xml(**args)
            cls.problem = ItemFactory.create(
                category="problem",
                parent_location=cls.sequential.location,
                display_name="Problem 1",
                format="Homework",
                data=problem_xml,
            )

            cls.video = ItemFactory.create(
                category="video",
                parent_location=cls.sequential.location,
                display_name="Video 1",
            )

            cls.html = ItemFactory.create(
                category="html",
                parent_location=cls.sequential.location,
                display_name="HTML 1",
            )
예제 #4
0
 def setUpClass(cls):
     super(TestStudentModuleGrading, cls).setUpClass()
     cls.course = CourseFactory.create()
     cls.chapter = ItemFactory.create(parent=cls.course,
                                      category="chapter",
                                      display_name="Test Chapter")
     cls.sequence = ItemFactory.create(parent=cls.chapter,
                                       category='sequential',
                                       display_name="Test Sequential 1",
                                       graded=True)
     cls.vertical = ItemFactory.create(parent=cls.sequence,
                                       category='vertical',
                                       display_name='Test Vertical 1')
     problem_xml = MultipleChoiceResponseXMLFactory().build_xml(
         question_text='The correct answer is Choice 3',
         choices=[False, False, True, False],
         choice_names=['choice_0', 'choice_1', 'choice_2', 'choice_3'])
     cls.problem = ItemFactory.create(parent=cls.vertical,
                                      category="problem",
                                      display_name="Test Problem",
                                      data=problem_xml)
     cls.request = get_mock_request(UserFactory())
     cls.user = cls.request.user
     cls.instructor = UserFactory(username='******', is_staff=True)
예제 #5
0
class MultipleChoiceProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
    """
    TestCase Class for Multiple Choice Problem Type
    """
    problem_name = 'MULTIPLE CHOICE TEST PROBLEM'
    problem_type = 'multiple choice'

    factory = MultipleChoiceResponseXMLFactory()

    partially_correct = False

    factory_kwargs = {
        'question_text': 'The correct answer is Choice 2',
        'choices': [False, False, True, False],
        'choice_names': ['choice_0', 'choice_1', 'choice_2', 'choice_3'],
    }
    status_indicators = {
        'correct': ['label.choicegroup_correct'],
        'incorrect': ['label.choicegroup_incorrect', 'span.incorrect'],
        'unanswered': ['span.unanswered'],
    }

    def setUp(self, *args, **kwargs):
        """
        Additional setup for MultipleChoiceProblemTypeTest
        """
        super(MultipleChoiceProblemTypeTest, self).setUp(*args, **kwargs)

    def answer_problem(self, correctness):
        """
        Answer multiple choice problem.
        """
        if correctness == 'incorrect':
            self.problem_page.click_choice("choice_choice_1")
        else:
            self.problem_page.click_choice("choice_choice_2")
예제 #6
0
 def setUpClass(cls):
     super(GradesEventIntegrationTest, cls).setUpClass()
     with cls.store.default_store(ModuleStoreEnum.Type.split):
         cls.course = CourseFactory.create()
         cls.chapter = ItemFactory.create(parent=cls.course,
                                          category="chapter",
                                          display_name="Test Chapter")
         cls.sequence = ItemFactory.create(parent=cls.chapter,
                                           category='sequential',
                                           display_name="Test Sequential 1",
                                           graded=True,
                                           format="Homework")
         cls.vertical = ItemFactory.create(parent=cls.sequence,
                                           category='vertical',
                                           display_name='Test Vertical 1')
         problem_xml = MultipleChoiceResponseXMLFactory().build_xml(
             question_text='The correct answer is Choice 2',
             choices=[False, False, True, False],
             choice_names=['choice_0', 'choice_1', 'choice_2', 'choice_3'])
         cls.problem = ItemFactory.create(parent=cls.vertical,
                                          category="problem",
                                          display_name="p1",
                                          data=problem_xml,
                                          metadata={'weight': 2})
    def setUp(self):
        """
        Test case scaffolding
        """
        super().setUp()
        self.course = CourseFactory.create(
            metadata={
                'entrance_exam_enabled': True,
            }
        )
        with self.store.bulk_operations(self.course.id):
            self.chapter = ItemFactory.create(
                parent=self.course,
                display_name='Overview'
            )
            self.welcome = ItemFactory.create(
                parent=self.chapter,
                display_name='Welcome'
            )
            ItemFactory.create(
                parent=self.course,
                category='chapter',
                display_name="Week 1"
            )
            self.chapter_subsection = ItemFactory.create(
                parent=self.chapter,
                category='sequential',
                display_name="Lesson 1"
            )
            chapter_vertical = ItemFactory.create(
                parent=self.chapter_subsection,
                category='vertical',
                display_name='Lesson 1 Vertical - Unit 1'
            )
            ItemFactory.create(
                parent=chapter_vertical,
                category="problem",
                display_name="Problem - Unit 1 Problem 1"
            )
            ItemFactory.create(
                parent=chapter_vertical,
                category="problem",
                display_name="Problem - Unit 1 Problem 2"
            )

            ItemFactory.create(
                category="instructor",
                parent=self.course,
                data="Instructor Tab",
                display_name="Instructor"
            )
            self.entrance_exam = ItemFactory.create(
                parent=self.course,
                category="chapter",
                display_name="Entrance Exam Section - Chapter 1",
                is_entrance_exam=True,
                in_entrance_exam=True
            )
            self.exam_1 = ItemFactory.create(
                parent=self.entrance_exam,
                category='sequential',
                display_name="Exam Sequential - Subsection 1",
                graded=True,
                in_entrance_exam=True
            )
            subsection = ItemFactory.create(
                parent=self.exam_1,
                category='vertical',
                display_name='Exam Vertical - Unit 1'
            )
            problem_xml = MultipleChoiceResponseXMLFactory().build_xml(
                question_text='The correct answer is Choice 3',
                choices=[False, False, True, False],
                choice_names=['choice_0', 'choice_1', 'choice_2', 'choice_3']
            )
            self.problem_1 = ItemFactory.create(
                parent=subsection,
                category="problem",
                display_name="Exam Problem - Problem 1",
                data=problem_xml
            )
            self.problem_2 = ItemFactory.create(
                parent=subsection,
                category="problem",
                display_name="Exam Problem - Problem 2"
            )

        add_entrance_exam_milestone(self.course, self.entrance_exam)

        self.course.entrance_exam_enabled = True
        self.course.entrance_exam_minimum_score_pct = 0.50
        self.course.entrance_exam_id = str(self.entrance_exam.scope_ids.usage_id)

        self.anonymous_user = AnonymousUserFactory()
        self.addCleanup(set_current_request, None)
        self.request = get_mock_request(UserFactory())
        modulestore().update_item(self.course, self.request.user.id)

        self.client.login(username=self.request.user.username, password="******")
        CourseEnrollment.enroll(self.request.user, self.course.id)

        self.expected_locked_toc = (
            [
                {
                    'active': True,
                    'sections': [
                        {
                            'url_name': 'Exam_Sequential_-_Subsection_1',
                            'display_name': 'Exam Sequential - Subsection 1',
                            'graded': True,
                            'format': '',
                            'due': None,
                            'active': True
                        }
                    ],
                    'url_name': 'Entrance_Exam_Section_-_Chapter_1',
                    'display_name': 'Entrance Exam Section - Chapter 1',
                    'display_id': 'entrance-exam-section-chapter-1',
                }
            ]
        )
        self.expected_unlocked_toc = (
            [
                {
                    'active': False,
                    'sections': [
                        {
                            'url_name': 'Welcome',
                            'display_name': 'Welcome',
                            'graded': False,
                            'format': '',
                            'due': None,
                            'active': False
                        },
                        {
                            'url_name': 'Lesson_1',
                            'display_name': 'Lesson 1',
                            'graded': False,
                            'format': '',
                            'due': None,
                            'active': False
                        }
                    ],
                    'url_name': 'Overview',
                    'display_name': 'Overview',
                    'display_id': 'overview'
                },
                {
                    'active': False,
                    'sections': [],
                    'url_name': 'Week_1',
                    'display_name': 'Week 1',
                    'display_id': 'week-1'
                },
                {
                    'active': False,
                    'sections': [],
                    'url_name': 'Instructor',
                    'display_name': 'Instructor',
                    'display_id': 'instructor'
                },
                {
                    'active': True,
                    'sections': [
                        {
                            'url_name': 'Exam_Sequential_-_Subsection_1',
                            'display_name': 'Exam Sequential - Subsection 1',
                            'graded': True,
                            'format': '',
                            'due': None,
                            'active': True
                        }
                    ],
                    'url_name': 'Entrance_Exam_Section_-_Chapter_1',
                    'display_name': 'Entrance Exam Section - Chapter 1',
                    'display_id': 'entrance-exam-section-chapter-1'
                }
            ]
        )
예제 #8
0
    def setUpClass(cls):
        super(TestGetModuleScore, cls).setUpClass()
        cls.course = CourseFactory.create()
        cls.chapter = ItemFactory.create(parent=cls.course,
                                         category="chapter",
                                         display_name="Test Chapter")
        cls.seq1 = ItemFactory.create(parent=cls.chapter,
                                      category='sequential',
                                      display_name="Test Sequential 1",
                                      graded=True)
        cls.seq2 = ItemFactory.create(parent=cls.chapter,
                                      category='sequential',
                                      display_name="Test Sequential 2",
                                      graded=True)
        cls.seq3 = ItemFactory.create(parent=cls.chapter,
                                      category='sequential',
                                      display_name="Test Sequential 3",
                                      graded=True)
        cls.vert1 = ItemFactory.create(parent=cls.seq1,
                                       category='vertical',
                                       display_name='Test Vertical 1')
        cls.vert2 = ItemFactory.create(parent=cls.seq2,
                                       category='vertical',
                                       display_name='Test Vertical 2')
        cls.vert3 = ItemFactory.create(parent=cls.seq3,
                                       category='vertical',
                                       display_name='Test Vertical 3')
        cls.randomize = ItemFactory.create(parent=cls.vert2,
                                           category='randomize',
                                           display_name='Test Randomize')
        cls.library_content = ItemFactory.create(
            parent=cls.vert3,
            category='library_content',
            display_name='Test Library Content')
        problem_xml = MultipleChoiceResponseXMLFactory().build_xml(
            question_text='The correct answer is Choice 3',
            choices=[False, False, True, False],
            choice_names=['choice_0', 'choice_1', 'choice_2', 'choice_3'])
        cls.problem1 = ItemFactory.create(parent=cls.vert1,
                                          category="problem",
                                          display_name="Test Problem 1",
                                          data=problem_xml)
        cls.problem2 = ItemFactory.create(parent=cls.vert1,
                                          category="problem",
                                          display_name="Test Problem 2",
                                          data=problem_xml)
        cls.problem3 = ItemFactory.create(parent=cls.randomize,
                                          category="problem",
                                          display_name="Test Problem 3",
                                          data=problem_xml)
        cls.problem4 = ItemFactory.create(parent=cls.randomize,
                                          category="problem",
                                          display_name="Test Problem 4",
                                          data=problem_xml)

        cls.problem5 = ItemFactory.create(parent=cls.library_content,
                                          category="problem",
                                          display_name="Test Problem 5",
                                          data=problem_xml)
        cls.problem6 = ItemFactory.create(parent=cls.library_content,
                                          category="problem",
                                          display_name="Test Problem 6",
                                          data=problem_xml)
예제 #9
0
class MultipleChoiceProblemTypeTest(ProblemTypeTestBase, ProblemTypeTestMixin):
    """
    TestCase Class for Multiple Choice Problem Type
    """
    problem_name = 'MULTIPLE CHOICE TEST PROBLEM'
    problem_type = 'multiple choice'

    factory = MultipleChoiceResponseXMLFactory()

    partially_correct = False

    factory_kwargs = {
        'question_text': 'The correct answer is Choice 2',
        'choices': [False, False, True, False],
        'choice_names': ['choice_0', 'choice_1', 'choice_2', 'choice_3'],
    }
    status_indicators = {
        'correct': ['label.choicegroup_correct'],
        'incorrect': ['label.choicegroup_incorrect', 'span.incorrect'],
        'unanswered': ['span.unanswered'],
    }

    def setUp(self, *args, **kwargs):
        """
        Additional setup for MultipleChoiceProblemTypeTest
        """
        super(MultipleChoiceProblemTypeTest, self).setUp(*args, **kwargs)

    def answer_problem(self, correctness):
        """
        Answer multiple choice problem.
        """
        if correctness == 'incorrect':
            self.problem_page.click_choice("choice_choice_1")
        else:
            self.problem_page.click_choice("choice_choice_2")

    @attr(shard=7)
    def test_can_show_answer(self):
        """
        Scenario: Verifies that show answer button is working as expected.

        Given that I am on courseware page
        And I can see a CAPA problem with show answer button
        When I click "Show Answer" button
        The correct answer is displayed with a single correctness indicator.
        """
        # Click the correct answer, but don't submit yet. No correctness shows.
        self.answer_problem('correct')
        self.assertFalse(self.problem_page.is_correct_choice_highlighted(correct_choices=[3]))

        # After submit, the answer should be marked as correct.
        self.problem_page.click_submit()
        self.assertTrue(self.problem_page.is_correct_choice_highlighted(correct_choices=[3]))

        # Switch to an incorrect answer. This will hide the correctness indicator.
        self.answer_problem('incorrect')
        self.assertFalse(self.problem_page.is_correct_choice_highlighted(correct_choices=[3]))

        # Now click Show Answer. A single correctness indicator should be shown.
        self.problem_page.click_show()
        self.assertTrue(self.problem_page.is_correct_choice_highlighted(correct_choices=[3]))

        # Finally, make sure that clicking Show Answer moved focus to the correct place.
        self.problem_page.wait_for_show_answer_notification()
예제 #10
0
 def setUp(self):
     super(TestCourseGradeLogging, self).setUp()
     self.course = CourseFactory.create()
     with self.store.bulk_operations(self.course.id):
         self.chapter = ItemFactory.create(
             parent=self.course,
             category="chapter",
             display_name="Test Chapter"
         )
         self.sequence = ItemFactory.create(
             parent=self.chapter,
             category='sequential',
             display_name="Test Sequential 1",
             graded=True
         )
         self.sequence_2 = ItemFactory.create(
             parent=self.chapter,
             category='sequential',
             display_name="Test Sequential 2",
             graded=True
         )
         self.sequence_3 = ItemFactory.create(
             parent=self.chapter,
             category='sequential',
             display_name="Test Sequential 3",
             graded=False
         )
         self.vertical = ItemFactory.create(
             parent=self.sequence,
             category='vertical',
             display_name='Test Vertical 1'
         )
         self.vertical_2 = ItemFactory.create(
             parent=self.sequence_2,
             category='vertical',
             display_name='Test Vertical 2'
         )
         self.vertical_3 = ItemFactory.create(
             parent=self.sequence_3,
             category='vertical',
             display_name='Test Vertical 3'
         )
         problem_xml = MultipleChoiceResponseXMLFactory().build_xml(
             question_text='The correct answer is Choice 2',
             choices=[False, False, True, False],
             choice_names=['choice_0', 'choice_1', 'choice_2', 'choice_3']
         )
         self.problem = ItemFactory.create(
             parent=self.vertical,
             category="problem",
             display_name="test_problem_1",
             data=problem_xml
         )
         self.problem_2 = ItemFactory.create(
             parent=self.vertical_2,
             category="problem",
             display_name="test_problem_2",
             data=problem_xml
         )
         self.problem_3 = ItemFactory.create(
             parent=self.vertical_3,
             category="problem",
             display_name="test_problem_3",
             data=problem_xml
         )
     self.request = get_mock_request(UserFactory())
     self.client.login(username=self.request.user.username, password="******")
     self.course_structure = get_course_blocks(self.request.user, self.course.location)
     self.subsection_grade_factory = SubsectionGradeFactory(self.request.user, self.course, self.course_structure)
     CourseEnrollment.enroll(self.request.user, self.course.id)
예제 #11
0
    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()
예제 #12
0
# 'correct', 'incorrect', and 'unanswered' keys are lists of CSS selectors
# the presence of any in the list is sufficient
PROBLEM_DICT = {
    'drop down': {
        'factory': OptionResponseXMLFactory(),
        'kwargs': {
            'question_text': 'The correct answer is Option 2',
            'options': ['Option 1', 'Option 2', 'Option 3', 'Option 4'],
            'correct_option': 'Option 2'
        },
        'correct': ['span.correct'],
        'incorrect': ['span.incorrect'],
        'unanswered': ['span.unanswered']
    },
    'multiple choice': {
        'factory': MultipleChoiceResponseXMLFactory(),
        'kwargs': {
            'question_text': 'The correct answer is Choice 3',
            'choices': [False, False, True, False],
            'choice_names': ['choice_0', 'choice_1', 'choice_2', 'choice_3']
        },
        'correct': ['label.choicegroup_correct', 'span.correct'],
        'incorrect': ['label.choicegroup_incorrect', 'span.incorrect'],
        'unanswered': ['span.unanswered']
    },
    'checkbox': {
        'factory': ChoiceResponseXMLFactory(),
        'kwargs': {
            'question_text': 'The correct answer is Choices 1 and 3',
            'choice_type': 'checkbox',
            'choices': [True, False, True, False, False],
예제 #13
0
    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,
        )