Esempio n. 1
0
 def test_unexpected_workflow_get_errors_wrapped(self, data, mock_get):
     with raises(workflow_api.AssessmentWorkflowInternalError):
         mock_get.side_effect = Exception("Kaboom!")
         submission = sub_api.create_submission(ITEM_1, "We talk TV!")
         workflow = workflow_api.create_workflow(submission["uuid"],
                                                 data["steps"])
         workflow_api.get_workflow_for_submission(workflow["uuid"], {})
    def test_submit_ora_test_data(self):
        """ Test for behavior of the submit step """
        self.cmd.submit_ora_test_data(COURSE_ID, CONFIG_1)

        # User 1 should have a submission, their workflow should be 'done', they should have a staff grade
        # and they should be locked.
        user_1_submission = sub_api.get_submissions(
            student_item(USERNAME_1, self.mock_block.location))[0]
        user_1_workflow = workflow_api.get_workflow_for_submission(
            user_1_submission['uuid'], None)
        assert user_1_workflow['status'] == 'done'
        user_1_assessment = staff_api.get_latest_staff_assessment(
            user_1_submission['uuid'])
        assert user_1_assessment['points_earned'] == 1
        assert user_1_assessment['scorer_id'] == anonymous_user_id(
            STAFF_USER_2)
        assert user_1_assessment['feedback'] == SUBMISSION_CONFIG_1[
            'gradeData']['overallFeedback']
        user_1_lock_owner = SubmissionGradingLock.get_submission_lock(
            user_1_submission['uuid']).owner_id
        assert user_1_lock_owner == anonymous_user_id(STAFF_USER_1)

        # User 2 should have a submission, their workflow should be 'waiting', they should not have a
        # staff grade and they should not be locked
        user_2_submission = sub_api.get_submissions(
            student_item(USERNAME_2, self.mock_block.location))[0]
        user_2_workflow = workflow_api.get_workflow_for_submission(
            user_2_submission['uuid'], None)
        assert user_2_workflow['status'] == 'waiting'
        user_2_assessment = staff_api.get_latest_staff_assessment(
            user_2_submission['uuid'])
        assert user_2_assessment is None
        assert SubmissionGradingLock.get_submission_lock(
            user_2_submission['uuid']) is None
Esempio n. 3
0
    def test_provisionally_done(self):
        """
        Test to ensure that blocking steps, such as peer, are not considered done and do not display a score
        if the submitter's requirements have not yet been met, even if a staff score has been recorded.

        This test also ensures that a user may submit peer assessments after having been staff assessed, which was
        a bug that had been previously present.
        """
        # Tim(student) makes a submission, for a problem that requires peer assessment
        tim_sub, _ = TestStaffAssessment._create_student_and_submission(
            "Tim", "Tim's answer", problem_steps=['peer'])
        # Bob(student) also makes a submission for that problem
        bob_sub, bob = TestStaffAssessment._create_student_and_submission(
            "Bob", "Bob's answer", problem_steps=['peer'])

        # Define peer requirements. Note that neither submission will fulfill must_be_graded_by
        requirements = {"peer": {"must_grade": 1, "must_be_graded_by": 2}}

        staff_score = "none"
        # Dumbledore(staff) uses override ability to provide a score for both submissions
        staff_api.create_assessment(
            tim_sub["uuid"],
            "Dumbledore",
            OPTIONS_SELECTED_DICT[staff_score]["options"],
            dict(),
            "",
            RUBRIC,
        )
        staff_api.create_assessment(
            bob_sub["uuid"],
            "Dumbledore",
            OPTIONS_SELECTED_DICT[staff_score]["options"],
            dict(),
            "",
            RUBRIC,
        )

        # Bob completes his peer assessment duties, Tim does not
        peer_api.get_submission_to_assess(bob_sub["uuid"], 1)
        peer_assess(bob_sub["uuid"], bob["student_id"],
                    OPTIONS_SELECTED_DICT["most"]["options"], dict(), "",
                    RUBRIC, requirements["peer"]["must_be_graded_by"])

        # Verify that Bob's submission is marked done and returns the proper score
        bob_workflow = workflow_api.get_workflow_for_submission(
            bob_sub["uuid"], requirements)
        self.assertEqual(bob_workflow["score"]["points_earned"],
                         OPTIONS_SELECTED_DICT[staff_score]["expected_points"])
        self.assertEqual(bob_workflow["status"], "done")

        # Verify that Tim's submission is not marked done, and he cannot get his score
        tim_workflow = workflow_api.get_workflow_for_submission(
            tim_sub["uuid"], requirements)
        self.assertEqual(tim_workflow["score"], None)
        self.assertNotEqual(tim_workflow["status"], "done")
Esempio n. 4
0
    def test_assessment_module_rollback_update_workflow(self):
        """
        Test that updates work when assessment modules roll back

        This test is designed to instantiate a workflow with an installed
        assessment module, then verify the workflow can be updated even when
        the status is set to an uninstalled assessment module.

        """
        requirements = {
            "special": {},
            "peer": {
                "must_grade": 1,
                "must_be_graded_by": 1
            },
            "self": {}
        }

        # We'll cheat to create the workflow with the new 'special' status,
        # otherwise the creation logic will not allow unknown an unknown status
        # to be set.
        real_steps = AssessmentWorkflow.STEPS
        AssessmentWorkflow.STEPS = ["special"] + real_steps
        workflow, submission = self._create_workflow_with_status(
            "user 1",
            "test/1/1",
            "peer-problem",
            "special",
            steps=["special", "peer", "self"])
        AssessmentWorkflow.STEPS = real_steps

        workflow_api.get_workflow_for_submission(
            submission["uuid"], requirements
        )

        peer_workflows = list(PeerWorkflow.objects.filter(submission_uuid=submission["uuid"]))
        self.assertTrue(peer_workflows)


        with patch.object(peer_api, 'submitter_is_finished') as mock_peer_submit:
            mock_peer_submit.return_value = True
            workflow = workflow_api.get_workflow_for_submission(
                submission["uuid"], requirements
            )
        self.assertEquals("self", workflow['status'])

        with patch.object(self_api, 'submitter_is_finished') as mock_self_submit:
            mock_self_submit.return_value = True
            workflow = workflow_api.get_workflow_for_submission(
                submission["uuid"], requirements
            )

        self.assertEquals("waiting", workflow['status'])
Esempio n. 5
0
    def test_create_assessment_does_not_block(self, after_type, after_assess):
        """
        Test to ensure that the presence of an override staff assessment only prevents new scores from being recorded;
        other assessments can still be made.
        """
        # Staff assessments do not block other staff scores from overriding, so skip that test
        if after_type == 'staff':
            return

        requirements = self.STEP_REQUIREMENTS
        if after_type == 'peer':
            requirements = {"peer": {"must_grade": 0, "must_be_graded_by": 1}}

        # Create assessment
        tim_sub, tim = self._create_student_and_submission(
            "Tim", "Tim's answer", problem_steps=[after_type])

        staff_score = "few"
        # Staff assess it
        staff_assessment = staff_api.create_assessment(
            tim_sub["uuid"],
            "Dumbledore",
            OPTIONS_SELECTED_DICT[staff_score]['options'],
            dict(),
            "",
            RUBRIC,
        )

        # Verify both assessment and workflow report correct score
        self.assertEqual(staff_assessment["points_earned"],
                         OPTIONS_SELECTED_DICT[staff_score]["expected_points"])
        workflow = workflow_api.get_workflow_for_submission(
            tim_sub["uuid"], requirements)
        # It's impossible to fake self requirements being complete, so we can't get the score for the self after_type
        if after_type != 'self':
            self.assertEqual(
                workflow["score"]["points_earned"],
                OPTIONS_SELECTED_DICT[staff_score]["expected_points"])

        # Now, non-force asses with a 'most' value
        # This was selected to match the value that the ai test will set
        unscored_assessment = OPTIONS_SELECTED_DICT["most"]
        assessment = after_assess(tim_sub["uuid"], tim["student_id"],
                                  unscored_assessment["options"])

        # Verify both assessment and workflow report correct score (workflow should report previous value)
        self.assertEqual(assessment["points_earned"],
                         unscored_assessment["expected_points"])
        workflow = workflow_api.get_workflow_for_submission(
            tim_sub["uuid"], requirements)
        self.assertEqual(workflow["score"]["points_earned"],
                         OPTIONS_SELECTED_DICT[staff_score]["expected_points"])
Esempio n. 6
0
    def test_provisionally_done(self):
        """
        Test to ensure that blocking steps, such as peer, are not considered done and do not display a score
        if the submitter's requirements have not yet been met, even if a staff score has been recorded.

        This test also ensures that a user may submit peer assessments after having been staff assessed, which was
        a bug that had been previously present.
        """
        # Tim(student) makes a submission, for a problem that requires peer assessment
        tim_sub, _ = TestStaffAssessment._create_student_and_submission("Tim", "Tim's answer", problem_steps=['peer'])
        # Bob(student) also makes a submission for that problem
        bob_sub, bob = TestStaffAssessment._create_student_and_submission("Bob", "Bob's answer", problem_steps=['peer'])

        # Define peer requirements. Note that neither submission will fulfill must_be_graded_by
        requirements = {"peer": {"must_grade": 1, "must_be_graded_by": 2}}

        staff_score = "none"
        # Dumbledore(staff) uses override ability to provide a score for both submissions
        staff_api.create_assessment(
            tim_sub["uuid"],
            "Dumbledore",
            OPTIONS_SELECTED_DICT[staff_score]["options"], dict(), "",
            RUBRIC,
        )
        staff_api.create_assessment(
            bob_sub["uuid"],
            "Dumbledore",
            OPTIONS_SELECTED_DICT[staff_score]["options"], dict(), "",
            RUBRIC,
        )

        # Bob completes his peer assessment duties, Tim does not
        peer_api.get_submission_to_assess(bob_sub["uuid"], 1)
        peer_assess(
            bob_sub["uuid"],
            bob["student_id"],
            OPTIONS_SELECTED_DICT["most"]["options"], dict(), "",
            RUBRIC,
            requirements["peer"]["must_be_graded_by"]
        )

        # Verify that Bob's submission is marked done and returns the proper score
        bob_workflow = workflow_api.get_workflow_for_submission(bob_sub["uuid"], requirements)
        self.assertEqual(bob_workflow["score"]["points_earned"], OPTIONS_SELECTED_DICT[staff_score]["expected_points"])
        self.assertEqual(bob_workflow["status"], "done")

        # Verify that Tim's submission is not marked done, and he cannot get his score
        tim_workflow = workflow_api.get_workflow_for_submission(tim_sub["uuid"], requirements)
        self.assertEqual(tim_workflow["score"], None)
        self.assertNotEqual(tim_workflow["status"], "done")
Esempio n. 7
0
    def test_create_assessment_score_overrides(self, key):
        """
        Test to ensure that scores can be overriden by a staff assessment using any value.
        """
        # Initially, self-asses with an all value
        initial_assessment = OPTIONS_SELECTED_DICT["all"]

        # Unless we're trying to override with an all value, then start with none
        if key == "all":
            initial_assessment = OPTIONS_SELECTED_DICT["none"]

        # Create assessment
        tim_sub, tim = self._create_student_and_submission(
            "Tim", "Tim's answer", problem_steps=['self'])

        # Self assess it
        self_assessment = self_assess(
            tim_sub["uuid"],
            tim["student_id"],
            initial_assessment["options"],
            dict(),
            "",
            RUBRIC,
        )

        # Verify both assessment and workflow report correct score
        self.assertEqual(self_assessment["points_earned"],
                         initial_assessment["expected_points"])
        workflow = workflow_api.get_workflow_for_submission(
            tim_sub["uuid"], self.STEP_REQUIREMENTS)
        self.assertEqual(workflow["score"]["points_earned"],
                         initial_assessment["expected_points"])

        # Now override with a staff assessment
        staff_assessment = staff_api.create_assessment(
            tim_sub["uuid"],
            "Dumbledore",
            OPTIONS_SELECTED_DICT[key]["options"],
            dict(),
            "",
            RUBRIC,
        )

        # Verify both assessment and workflow report correct score
        self.assertEqual(staff_assessment["points_earned"],
                         OPTIONS_SELECTED_DICT[key]["expected_points"])
        workflow = workflow_api.get_workflow_for_submission(
            tim_sub["uuid"], self.STEP_REQUIREMENTS)
        self.assertEqual(workflow["score"]["points_earned"],
                         OPTIONS_SELECTED_DICT[key]["expected_points"])
Esempio n. 8
0
    def test_create_workflow(self, data):
        first_step = data["steps"][0] if data["steps"] else "peer"
        if "ai" in data["steps"]:
            first_step = data["steps"][1] if len(
                data["steps"]) > 1 else "waiting"
        submission = sub_api.create_submission(ITEM_1, ANSWER_1)
        workflow = workflow_api.create_workflow(submission["uuid"],
                                                data["steps"])

        workflow_keys = set(workflow.keys())
        self.assertEqual(
            workflow_keys, {
                'submission_uuid', 'status', 'created', 'modified', 'score',
                'assessment_score_priority'
            })
        self.assertEqual(workflow["submission_uuid"], submission["uuid"])
        self.assertEqual(workflow["status"], first_step)

        workflow_from_get = workflow_api.get_workflow_for_submission(
            submission["uuid"], data["requirements"])
        del workflow_from_get['status_details']
        self.assertEqual(workflow, workflow_from_get)

        # Test that the Peer Workflow is, or is not created, based on when peer
        # is a step in the workflow.
        if first_step == "peer":
            peer_workflow = PeerWorkflow.objects.get(
                submission_uuid=submission["uuid"])
            self.assertIsNotNone(peer_workflow)
        else:
            peer_workflows = list(
                PeerWorkflow.objects.filter(
                    submission_uuid=submission["uuid"]))
            self.assertFalse(peer_workflows)
Esempio n. 9
0
    def get_workflow_info(self, submission_uuid=None):
        """
        Retrieve a description of the student's progress in a workflow.
        Note that this *may* update the workflow status if it's changed.

        Keyword Arguments:
            submission_uuid (str): The submission associated with the workflow to return.
                Defaults to the submission created by the current student.

        Returns:
            dict

        Raises:
            AssessmentWorkflowError
        """
        if self.is_team_assignment():
            return self.get_team_workflow_info()

        if submission_uuid is None:
            submission_uuid = self.get_submission_uuid()

        if submission_uuid is None:
            return {}
        return workflow_api.get_workflow_for_submission(
            submission_uuid, self.workflow_requirements())
Esempio n. 10
0
    def test_create_workflow(self, data):
        first_step = data["steps"][0] if data["steps"] else "peer"
        submission = sub_api.create_submission(ITEM_1, "Shoot Hot Rod")
        workflow = workflow_api.create_workflow(submission["uuid"], data["steps"])

        workflow_keys = set(workflow.keys())
        self.assertEqual(
            workflow_keys,
            {
                'submission_uuid', 'uuid', 'status', 'created', 'modified', 'score'
            }
        )
        self.assertEqual(workflow["submission_uuid"], submission["uuid"])
        self.assertEqual(workflow["status"], first_step)

        workflow_from_get = workflow_api.get_workflow_for_submission(
            submission["uuid"], data["requirements"]
        )
        del workflow_from_get['status_details']
        self.assertEqual(workflow, workflow_from_get)

        # Test that the Peer Workflow is, or is not created, based on when peer
        # is a step in the workflow.
        if "peer" == first_step:
            peer_workflow = PeerWorkflow.objects.get(submission_uuid=submission["uuid"])
            self.assertIsNotNone(peer_workflow)
        else:
            peer_workflows = list(PeerWorkflow.objects.filter(submission_uuid=submission["uuid"]))
            self.assertFalse(peer_workflows)
Esempio n. 11
0
    def test_create_assessment_type_overrides(self, initial_type,
                                              initial_assess):
        """
        Test to ensure that any assesment, even a staff assessment, can be overriden by a staff assessment.
        """
        # Initially, asses with a 'most' value
        # This was selected to match the value that the ai test will set
        initial_assessment = OPTIONS_SELECTED_DICT["most"]

        # Create assessment
        tim_sub, tim = self._create_student_and_submission(
            "Tim", "Tim's answer", problem_steps=[initial_type])

        # Initially assess it
        assessment = initial_assess(tim_sub["uuid"], tim["student_id"],
                                    initial_assessment["options"])
        # and update workflow with new scores
        requirements = self.STEP_REQUIREMENTS
        if initial_type == 'peer':
            requirements = {"peer": {"must_grade": 0, "must_be_graded_by": 1}}

        # Verify both assessment and workflow report correct score
        self.assertEqual(assessment["points_earned"],
                         initial_assessment["expected_points"])
        workflow = workflow_api.get_workflow_for_submission(
            tim_sub["uuid"], requirements)
        self.assertEqual(workflow["score"]["points_earned"],
                         initial_assessment["expected_points"])

        staff_score = "few"
        # Now override with a staff assessment
        staff_assessment = staff_api.create_assessment(
            tim_sub["uuid"],
            "Dumbledore",
            OPTIONS_SELECTED_DICT[staff_score]["options"],
            dict(),
            "",
            RUBRIC,
        )

        # Verify both assessment and workflow report correct score
        self.assertEqual(staff_assessment["points_earned"],
                         OPTIONS_SELECTED_DICT[staff_score]["expected_points"])
        workflow = workflow_api.get_workflow_for_submission(
            tim_sub["uuid"], requirements)
        self.assertEqual(workflow["score"]["points_earned"],
                         OPTIONS_SELECTED_DICT[staff_score]["expected_points"])
Esempio n. 12
0
    def test_update_with_override(self):
        """
        Test that, when viewing a submission with a staff override present, the workflow is not updated repeatedly.

        See TNL-6092 for some historical context.
        """
        tim_sub, _ = TestStaffAssessment._create_student_and_submission("Tim", "Tim's answer", problem_steps=['self'])
        staff_api.create_assessment(
            tim_sub["uuid"],
            "Dumbledore",
            OPTIONS_SELECTED_DICT["none"]["options"], {}, "",
            RUBRIC,
        )
        workflow_api.get_workflow_for_submission(tim_sub["uuid"], {})
        with mock.patch('openassessment.workflow.models.sub_api.reset_score') as mock_reset:
            workflow_api.get_workflow_for_submission(tim_sub["uuid"], {})
            self.assertFalse(mock_reset.called)
Esempio n. 13
0
    def test_update_with_override(self):
        """
        Test that, when viewing a submission with a staff override present, the workflow is not updated repeatedly.

        See TNL-6092 for some historical context.
        """
        tim_sub, _ = TestStaffAssessment._create_student_and_submission("Tim", "Tim's answer", problem_steps=['self'])
        staff_api.create_assessment(
            tim_sub["uuid"],
            "Dumbledore",
            OPTIONS_SELECTED_DICT["none"]["options"], dict(), "",
            RUBRIC,
        )
        workflow_api.get_workflow_for_submission(tim_sub["uuid"], {})
        with mock.patch('openassessment.workflow.models.sub_api.reset_score') as mock_reset:
            workflow_api.get_workflow_for_submission(tim_sub["uuid"], {})
            self.assertFalse(mock_reset.called)
Esempio n. 14
0
 def test_ai_score_set(self, mock_score, mock_is_finished):
     submission = sub_api.create_submission(ITEM_1, ANSWER_2)
     mock_is_finished.return_value = True
     score = {"points_earned": 7, "points_possible": 10}
     mock_score.return_value = score
     workflow_api.create_workflow(submission["uuid"], ["ai"], ON_INIT_PARAMS)
     workflow = workflow_api.get_workflow_for_submission(submission["uuid"], {})
     self.assertEquals(workflow["score"]["points_earned"], score["points_earned"])
     self.assertEquals(workflow["score"]["points_possible"], score["points_possible"])
Esempio n. 15
0
 def test_ai_score_set(self, mock_score, mock_is_finished):
     submission = sub_api.create_submission(ITEM_1, "Ultra Magnus fumble")
     mock_is_finished.return_value = True
     score = {"points_earned": 7, "points_possible": 10}
     mock_score.return_value = score
     workflow_api.create_workflow(submission["uuid"], ["ai"], ON_INIT_PARAMS)
     workflow = workflow_api.get_workflow_for_submission(submission["uuid"], {})
     self.assertEquals(workflow["score"]["points_earned"], score["points_earned"])
     self.assertEquals(workflow["score"]["points_possible"], score["points_possible"])
Esempio n. 16
0
    def test_create_assessment_does_not_block(self, after_type, after_assess):
        """
        Test to ensure that the presence of an override staff assessment only prevents new scores from being recorded;
        other assessments can still be made.
        """
        # Staff assessments do not block other staff scores from overriding, so skip that test
        if after_type == 'staff':
            return

        requirements = self.STEP_REQUIREMENTS
        if after_type == 'peer':
            requirements = {"peer": {"must_grade": 0, "must_be_graded_by": 1}}

        # Create assessment
        tim_sub, tim = self._create_student_and_submission("Tim", "Tim's answer", problem_steps=[after_type])

        staff_score = "few"
        # Staff assess it
        staff_assessment = staff_api.create_assessment(
            tim_sub["uuid"],
            "Dumbledore",
            OPTIONS_SELECTED_DICT[staff_score]['options'], dict(), "",
            RUBRIC,
        )

        # Verify both assessment and workflow report correct score
        self.assertEqual(staff_assessment["points_earned"], OPTIONS_SELECTED_DICT[staff_score]["expected_points"])
        workflow = workflow_api.get_workflow_for_submission(tim_sub["uuid"], requirements)
        # It's impossible to fake self requirements being complete, so we can't get the score for the self after_type
        if after_type != 'self':
            self.assertEqual(workflow["score"]["points_earned"], OPTIONS_SELECTED_DICT[staff_score]["expected_points"])

        # Now, non-force asses with a 'most' value
        # This was selected to match the value that the ai test will set
        unscored_assessment = OPTIONS_SELECTED_DICT["most"]
        assessment = after_assess(tim_sub["uuid"], tim["student_id"], unscored_assessment["options"])

        # Verify both assessment and workflow report correct score (workflow should report previous value)
        self.assertEqual(assessment["points_earned"], unscored_assessment["expected_points"])
        workflow = workflow_api.get_workflow_for_submission(tim_sub["uuid"], requirements)
        self.assertEqual(workflow["score"]["points_earned"], OPTIONS_SELECTED_DICT[staff_score]["expected_points"])
Esempio n. 17
0
 def _verify_done_state(self, uuid, requirements, expect_done=True):
     """
     Asserts that a submision and workflow are (or aren't) set to status "done".
     A False value for expect_done will confirm an assessment/workflow are NOT done.
     """
     workflow = workflow_api.get_workflow_for_submission(uuid, requirements)
     if expect_done:
         self.assertTrue(staff_api.assessment_is_finished(uuid, requirements))
         self.assertEqual(workflow["status"], "done")
     else:
         self.assertFalse(staff_api.assessment_is_finished(uuid, requirements))
         self.assertNotEqual(workflow["status"], "done")
Esempio n. 18
0
 def _verify_done_state(self, uuid, requirements, expect_done=True):
     """
     Asserts that a submision and workflow are (or aren't) set to status "done".
     A False value for expect_done will confirm an assessment/workflow are NOT done.
     """
     workflow = workflow_api.get_workflow_for_submission(uuid, requirements)
     if expect_done:
         self.assertTrue(staff_api.assessment_is_finished(uuid, requirements))
         self.assertEqual(workflow["status"], "done")
     else:
         self.assertFalse(staff_api.assessment_is_finished(uuid, requirements))
         self.assertNotEqual(workflow["status"], "done")
Esempio n. 19
0
    def test_create_assessment_score_overrides(self, key):
        """
        Test to ensure that scores can be overriden by a staff assessment using any value.
        """
        # Initially, self-asses with an all value
        initial_assessment = OPTIONS_SELECTED_DICT["all"]

        # Unless we're trying to override with an all value, then start with none
        if key == "all":
            initial_assessment = OPTIONS_SELECTED_DICT["none"]

        # Create assessment
        tim_sub, tim = self._create_student_and_submission("Tim", "Tim's answer", problem_steps=['self'])

        # Self assess it
        self_assessment = self_assess(
            tim_sub["uuid"],
            tim["student_id"],
            initial_assessment["options"], dict(), "",
            RUBRIC,
        )

        # Verify both assessment and workflow report correct score
        self.assertEqual(self_assessment["points_earned"], initial_assessment["expected_points"])
        workflow = workflow_api.get_workflow_for_submission(tim_sub["uuid"], self.STEP_REQUIREMENTS)
        self.assertEqual(workflow["score"]["points_earned"], initial_assessment["expected_points"])

        # Now override with a staff assessment
        staff_assessment = staff_api.create_assessment(
            tim_sub["uuid"],
            "Dumbledore",
            OPTIONS_SELECTED_DICT[key]["options"], dict(), "",
            RUBRIC,
        )

        # Verify both assessment and workflow report correct score
        self.assertEqual(staff_assessment["points_earned"], OPTIONS_SELECTED_DICT[key]["expected_points"])
        workflow = workflow_api.get_workflow_for_submission(tim_sub["uuid"], self.STEP_REQUIREMENTS)
        self.assertEqual(workflow["score"]["points_earned"], OPTIONS_SELECTED_DICT[key]["expected_points"])
Esempio n. 20
0
    def test_create_assessment_type_overrides(self, initial_type, initial_assess):
        """
        Test to ensure that any assesment, even a staff assessment, can be overriden by a staff assessment.
        """
        # Initially, asses with a 'most' value
        # This was selected to match the value that the ai test will set
        initial_assessment = OPTIONS_SELECTED_DICT["most"]

        # Create assessment
        tim_sub, tim = self._create_student_and_submission("Tim", "Tim's answer", problem_steps=[initial_type])

        # Initially assess it
        assessment = initial_assess(tim_sub["uuid"], tim["student_id"], initial_assessment["options"])
        # and update workflow with new scores
        requirements = self.STEP_REQUIREMENTS
        if initial_type == 'peer':
            requirements = {"peer": {"must_grade": 0, "must_be_graded_by": 1}}

        # Verify both assessment and workflow report correct score
        self.assertEqual(assessment["points_earned"], initial_assessment["expected_points"])
        workflow = workflow_api.get_workflow_for_submission(tim_sub["uuid"], requirements)
        self.assertEqual(workflow["score"]["points_earned"], initial_assessment["expected_points"])

        staff_score = "few"
        # Now override with a staff assessment
        staff_assessment = staff_api.create_assessment(
            tim_sub["uuid"],
            "Dumbledore",
            OPTIONS_SELECTED_DICT[staff_score]["options"], dict(), "",
            RUBRIC,
        )

        # Verify both assessment and workflow report correct score
        self.assertEqual(staff_assessment["points_earned"], OPTIONS_SELECTED_DICT[staff_score]["expected_points"])
        workflow = workflow_api.get_workflow_for_submission(tim_sub["uuid"], requirements)
        self.assertEqual(workflow["score"]["points_earned"], OPTIONS_SELECTED_DICT[staff_score]["expected_points"])
Esempio n. 21
0
    def get_workflow_info(self):
        """
        Retrieve a description of the student's progress in a workflow.
        Note that this *may* update the workflow status if it's changed.

        Returns:
            dict

        Raises:
            AssessmentWorkflowError
        """
        if not self.submission_uuid:
            return {}
        return workflow_api.get_workflow_for_submission(
            self.submission_uuid, self.workflow_requirements())
Esempio n. 22
0
    def get_workflow_info(self):
        """
        Retrieve a description of the student's progress in a workflow.
        Note that this *may* update the workflow status if it's changed.

        Returns:
            dict

        Raises:
            AssessmentWorkflowError
        """
        if not self.submission_uuid:
            return {}
        return workflow_api.get_workflow_for_submission(
            self.submission_uuid, self.workflow_requirements()
        )
Esempio n. 23
0
    def test_create_workflow(self, data):
        first_step = data["steps"][0] if data["steps"] else "peer"
        if "ai" in data["steps"]:
            first_step = data["steps"][1] if len(
                data["steps"]) > 1 else "waiting"
        submission = sub_api.create_submission(ITEM_1, ANSWER_1)
        workflow = workflow_api.create_workflow(submission["uuid"],
                                                data["steps"])

        workflow_keys = set(workflow.keys())
        self.assertEqual(
            workflow_keys, {
                'submission_uuid', 'status', 'created', 'modified', 'score',
                'assessment_score_priority'
            })
        self.assertEqual(workflow["submission_uuid"], submission["uuid"])
        self.assertEqual(workflow["status"], first_step)

        workflow_from_get = workflow_api.get_workflow_for_submission(
            submission["uuid"], data["requirements"])
        del workflow_from_get['status_details']

        # as peer step is skipable, we expect next possible status to be current status
        if first_step == 'peer' and data["steps"].index('peer') < len(
                data["steps"]) - 1:
            workflow = dict(workflow)
            workflow['status'] = data["steps"][data["steps"].index('peer') + 1]
            workflow_from_get = dict(workflow_from_get)

            # the change in `workflow` variable causes modified field to get changed.
            del workflow['modified']
            del workflow_from_get['modified']

        self.assertEqual(workflow, workflow_from_get)

        # Test that the Peer Workflow is, or is not created, based on when peer
        # is a step in the workflow.
        if first_step == "peer":
            peer_workflow = PeerWorkflow.objects.get(
                submission_uuid=submission["uuid"])
            self.assertIsNotNone(peer_workflow)
        else:
            peer_workflows = list(
                PeerWorkflow.objects.filter(
                    submission_uuid=submission["uuid"]))
            self.assertFalse(peer_workflows)
Esempio n. 24
0
    def test_create_workflow(self):
        submission = sub_api.create_submission(ITEM_1, "Shoot Hot Rod")
        workflow = workflow_api.create_workflow(submission["uuid"])

        workflow_keys = set(workflow.keys())
        self.assertEqual(
            workflow_keys,
            {
                'submission_uuid', 'uuid', 'status', 'created', 'modified', 'score'
            }
        )
        self.assertEqual(workflow["submission_uuid"], submission["uuid"])
        self.assertEqual(workflow["status"], "peer")

        workflow_from_get = workflow_api.get_workflow_for_submission(
            submission["uuid"], REQUIREMENTS
        )
        del workflow_from_get['status_details']
        self.assertEqual(workflow, workflow_from_get)
Esempio n. 25
0
    def test_update_peer_workflow(self):
        submission = sub_api.create_submission(ITEM_1, ANSWER_1)
        workflow = workflow_api.create_workflow(submission["uuid"],
                                                ["training", "peer"])
        StudentTrainingWorkflow.create_workflow(
            submission_uuid=submission["uuid"])
        requirements = {
            "training": {
                "num_required": 2
            },
            "peer": {
                "must_grade": 5,
                "must_be_graded_by": 3
            }
        }
        workflow_keys = set(workflow.keys())
        self.assertEqual(
            workflow_keys, {
                'submission_uuid', 'status', 'created', 'modified', 'score',
                'assessment_score_priority'
            })
        self.assertEqual(workflow["submission_uuid"], submission["uuid"])
        self.assertEqual(workflow["status"], "training")

        peer_workflows = list(
            PeerWorkflow.objects.filter(submission_uuid=submission["uuid"]))
        self.assertFalse(peer_workflows)

        workflow_from_get = workflow_api.get_workflow_for_submission(
            submission["uuid"], requirements)

        del workflow_from_get['status_details']
        self.assertEqual(workflow, workflow_from_get)

        requirements["training"]["num_required"] = 0
        workflow = workflow_api.update_from_assessments(
            submission["uuid"], requirements)

        # New step is Peer, and a Workflow has been created.
        self.assertEqual(workflow["status"], "peer")
        peer_workflow = PeerWorkflow.objects.get(
            submission_uuid=submission["uuid"])
        self.assertIsNotNone(peer_workflow)
    def assert_submission_created(self, user, expected_graded_by,
                                  expected_locked_by):
        submission = sub_api.get_submissions(
            student_item(user, self.mock_block.location))[0]
        workflow = workflow_api.get_workflow_for_submission(
            submission['uuid'], None)
        assessment = staff_api.get_latest_staff_assessment(submission['uuid'])
        lock = SubmissionGradingLock.get_submission_lock(submission['uuid'])

        if expected_graded_by:
            assert workflow['status'] == 'done'
            assert assessment['scorer_id'] == anonymous_user_id(
                expected_graded_by)
        else:
            assert workflow['status'] == 'waiting'
            assert assessment is None

        if expected_locked_by:
            assert lock is not None
            assert lock.owner_id == anonymous_user_id(STAFF_USER_1)
Esempio n. 27
0
    def test_create_workflow(self, data):
        first_step = data["steps"][0] if data["steps"] else "peer"
        submission = sub_api.create_submission(ITEM_1, "Shoot Hot Rod")
        workflow = workflow_api.create_workflow(submission["uuid"], data["steps"])

        workflow_keys = set(workflow.keys())
        self.assertEqual(
            workflow_keys,
            {
                'submission_uuid', 'uuid', 'status', 'created', 'modified', 'score'
            }
        )
        self.assertEqual(workflow["submission_uuid"], submission["uuid"])
        self.assertEqual(workflow["status"], first_step)

        workflow_from_get = workflow_api.get_workflow_for_submission(
            submission["uuid"], data["requirements"]
        )
        del workflow_from_get['status_details']
        self.assertEqual(workflow, workflow_from_get)
Esempio n. 28
0
def get_workflow_info(submission_uuid, oa_item):
    assessments = oa_item.rubric_assessments
    requirements = {}

    peer_assessment_module = get_assessment_module(assessments, 'peer-assessment')
    if peer_assessment_module:
        requirements["peer"] = {
            "must_grade": peer_assessment_module["must_grade"],
            "must_be_graded_by": peer_assessment_module["must_be_graded_by"]
        }

    training_module = get_assessment_module(assessments, 'student-training')
    if training_module:
        requirements["training"] = {
            "num_required": len(training_module["examples"])
        }

    # Note that this *may* update the workflow status if it's changed.
    # If the status is already `done`, the status stands immobile.
    return workflow_api.get_workflow_for_submission(submission_uuid, requirements)
Esempio n. 29
0
    def test_update_peer_workflow(self):
        submission = sub_api.create_submission(ITEM_1, "Shoot Hot Rod")
        workflow = workflow_api.create_workflow(submission["uuid"], ["training", "peer"], ON_INIT_PARAMS)
        StudentTrainingWorkflow.create_workflow(submission_uuid=submission["uuid"])
        requirements = {
            "training": {
                "num_required": 2
            },
            "peer": {
                "must_grade": 5,
                "must_be_graded_by": 3
            }
        }
        workflow_keys = set(workflow.keys())
        self.assertEqual(
            workflow_keys,
            {
                'override_score',
                'submission_uuid', 'uuid', 'status', 'created', 'modified', 'score'
            }
        )
        self.assertEqual(workflow["submission_uuid"], submission["uuid"])
        self.assertEqual(workflow["status"], "training")

        peer_workflows = list(PeerWorkflow.objects.filter(submission_uuid=submission["uuid"]))
        self.assertFalse(peer_workflows)

        workflow_from_get = workflow_api.get_workflow_for_submission(
            submission["uuid"], requirements
        )

        del workflow_from_get['status_details']
        self.assertEqual(workflow, workflow_from_get)

        requirements["training"]["num_required"] = 0
        workflow = workflow_api.update_from_assessments(submission["uuid"], requirements)

        # New step is Peer, and a Workflow has been created.
        self.assertEqual(workflow["status"], "peer")
        peer_workflow = PeerWorkflow.objects.get(submission_uuid=submission["uuid"])
        self.assertIsNotNone(peer_workflow)
Esempio n. 30
0
def get_workflow_info(submission_uuid, oa_item):
    assessments = oa_item.rubric_assessments
    requirements = {}

    peer_assessment_module = get_assessment_module(assessments,
                                                   'peer-assessment')
    if peer_assessment_module:
        requirements["peer"] = {
            "must_grade": peer_assessment_module["must_grade"],
            "must_be_graded_by": peer_assessment_module["must_be_graded_by"]
        }

    training_module = get_assessment_module(assessments, 'student-training')
    if training_module:
        requirements["training"] = {
            "num_required": len(training_module["examples"])
        }

    # Note that this *may* update the workflow status if it's changed.
    # If the status is already `done`, the status stands immobile.
    return workflow_api.get_workflow_for_submission(submission_uuid,
                                                    requirements)
Esempio n. 31
0
    def get_workflow_info(self, submission_uuid=None):
        """
        Retrieve a description of the student's progress in a workflow.
        Note that this *may* update the workflow status if it's changed.

        Keyword Arguments:
            submission_uuid (str): The submission associated with the workflow to return.
                Defaults to the submission created by the current student.

        Returns:
            dict

        Raises:
            AssessmentWorkflowError
        """
        if submission_uuid is None:
            submission_uuid = self.submission_uuid
            if submission_uuid is None:
                return {}
        return workflow_api.get_workflow_for_submission(
            submission_uuid, self.workflow_requirements()
        )
Esempio n. 32
0
 def test_get_assessment_workflow_expected_errors(self):
     with self.assertRaises(workflow_api.AssessmentWorkflowNotFoundError):
         workflow_api.get_workflow_for_submission("0000000000000", REQUIREMENTS)
     with self.assertRaises(workflow_api.AssessmentWorkflowRequestError):
         workflow_api.get_workflow_for_submission(123, REQUIREMENTS)
Esempio n. 33
0
 def test_unexpected_workflow_get_errors_wrapped(self, data, mock_get):
     mock_get.side_effect = Exception("Kaboom!")
     submission = sub_api.create_submission(ITEM_1, "We talk TV!")
     workflow = workflow_api.create_workflow(submission["uuid"], data["steps"])
     workflow_api.get_workflow_for_submission(workflow["uuid"], {})
Esempio n. 34
0
    def test_peer_assessment_workflow(self):
        tim_sub, tim = self._create_student_and_submission("Tim", "Tim's answer")
        bob_sub, bob = self._create_student_and_submission("Bob", "Bob's answer")
        sally_sub, sally = self._create_student_and_submission("Sally", "Sally's answer")
        jim_sub, jim = self._create_student_and_submission("Jim", "Jim's answer")
        self._create_student_and_submission("Buffy", "Buffy's answer")
        self._create_student_and_submission("Xander", "Xander's answer")

        # Tim should not have a score, because he has not evaluated enough
        # peer submissions.
        requirements = {
            "peer": {
                "must_grade": REQUIRED_GRADED,
                "must_be_graded_by": REQUIRED_GRADED_BY,
            }
        }
        score = workflow_api.get_workflow_for_submission(
            tim_sub["uuid"], requirements
        )["score"]
        self.assertIsNone(score)

        for i in range(5):
            self.assertEquals((False, i), peer_api.has_finished_required_evaluating(tim_sub['uuid'], REQUIRED_GRADED))
            sub = peer_api.get_submission_to_assess(tim_sub['uuid'], REQUIRED_GRADED)
            peer_api.create_assessment(
                tim_sub["uuid"], tim["student_id"],
                ASSESSMENT_DICT['options_selected'],
                ASSESSMENT_DICT['criterion_feedback'],
                ASSESSMENT_DICT['overall_feedback'],
                RUBRIC_DICT,
                REQUIRED_GRADED_BY,
            )

        self.assertEquals((True, 5), peer_api.has_finished_required_evaluating(tim_sub['uuid'], REQUIRED_GRADED))

        # Tim should not have a score, because his submission does not have
        # enough assessments.
        self.assertIsNone(sub_api.get_score(STUDENT_ITEM))

        sub = peer_api.get_submission_to_assess(bob_sub['uuid'], REQUIRED_GRADED)
        self.assertEqual(sub["uuid"], tim_sub["uuid"])
        peer_api.create_assessment(
            bob_sub["uuid"], bob["student_id"],
            ASSESSMENT_DICT['options_selected'],
            ASSESSMENT_DICT['criterion_feedback'],
            ASSESSMENT_DICT['overall_feedback'],
            RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        sub = peer_api.get_submission_to_assess(sally_sub['uuid'], REQUIRED_GRADED)
        self.assertEqual(sub["uuid"], tim_sub["uuid"])
        peer_api.create_assessment(
            sally_sub["uuid"], sally["student_id"],
            ASSESSMENT_DICT_FAIL['options_selected'],
            ASSESSMENT_DICT_FAIL['criterion_feedback'],
            ASSESSMENT_DICT_FAIL['overall_feedback'],
            RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        sub = peer_api.get_submission_to_assess(jim_sub['uuid'], REQUIRED_GRADED)
        self.assertEqual(sub["uuid"], tim_sub["uuid"])
        peer_api.create_assessment(
            jim_sub["uuid"], jim["student_id"],
            ASSESSMENT_DICT_PASS['options_selected'],
            ASSESSMENT_DICT_PASS['criterion_feedback'],
            ASSESSMENT_DICT_PASS['overall_feedback'],
            RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        # Tim has met the critera, and should now be complete.
        requirements = {
            'must_grade': REQUIRED_GRADED,
            'must_be_graded_by': REQUIRED_GRADED_BY
        }
        self.assertTrue(peer_api.is_complete(tim_sub["uuid"], requirements))
Esempio n. 35
0
 def test_get_assessment_workflow_expected_errors(self, data):
     with self.assertRaises(workflow_api.AssessmentWorkflowNotFoundError):
         workflow_api.get_workflow_for_submission("0000000000000", data["requirements"])
     with self.assertRaises(workflow_api.AssessmentWorkflowRequestError):
         workflow_api.get_workflow_for_submission(123, data["requirements"])
Esempio n. 36
0
    def test_completeness(self):
        """
        Verify that a submission in the peer workflow is only marked complete
        when we intend it to be. Incomplete assessments should never be
        included in a grade.
        """
        tim_sub, tim = self._create_student_and_submission("Tim", "Tim's answer")
        bob_sub, bob = self._create_student_and_submission("Bob", "Bob's answer")
        sally_sub, sally = self._create_student_and_submission("Sally", "Sally's answer")
        jim_sub, jim = self._create_student_and_submission("Jim", "Jim's answer")
        self._create_student_and_submission("Buffy", "Buffy's answer")
        self._create_student_and_submission("Xander", "Xander's answer")

        # Tim should not have a score, because he has not evaluated enough
        # peer submissions.
        requirements = {
            "peer": {
                "must_grade": REQUIRED_GRADED,
                "must_be_graded_by": REQUIRED_GRADED_BY,
                }
        }
        score = workflow_api.get_workflow_for_submission(
            tim_sub["uuid"], requirements
        )["score"]
        self.assertIsNone(score)

        # Bob and Sally pull Tim's submission for peer assessment, but do not
        # grade him right away.
        sub = peer_api.get_submission_to_assess(bob_sub['uuid'], REQUIRED_GRADED_BY)
        self.assertEqual(sub["uuid"], tim_sub["uuid"])

        sub = peer_api.get_submission_to_assess(sally_sub['uuid'], REQUIRED_GRADED_BY)
        self.assertEqual(sub["uuid"], tim_sub["uuid"])

        # Jim pulls Tim's submission, then grades it immediately.
        sub = peer_api.get_submission_to_assess(jim_sub['uuid'], REQUIRED_GRADED_BY)
        self.assertEqual(sub["uuid"], tim_sub["uuid"])

        peer_api.create_assessment(
            jim_sub["uuid"], jim["student_id"],
            ASSESSMENT_DICT['options_selected'],
            ASSESSMENT_DICT['criterion_feedback'],
            ASSESSMENT_DICT['overall_feedback'],
            RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        # Tim should have no score.
        score = workflow_api.get_workflow_for_submission(
            tim_sub["uuid"], requirements
        )["score"]
        self.assertIsNone(score)

        # Tim's workflow should not be fully graded
        self.assertIsNone(PeerWorkflow.objects.get(student_id=tim["student_id"]).grading_completed_at)

        peer_api.create_assessment(
            bob_sub["uuid"], bob["student_id"],
            ASSESSMENT_DICT['options_selected'],
            ASSESSMENT_DICT['criterion_feedback'],
            ASSESSMENT_DICT['overall_feedback'],
            RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        peer_api.create_assessment(
            sally_sub["uuid"], sally["student_id"],
            ASSESSMENT_DICT['options_selected'],
            ASSESSMENT_DICT['criterion_feedback'],
            ASSESSMENT_DICT['overall_feedback'],
            RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        # Tim should not have a score since he did not grade peers..
        score = workflow_api.get_workflow_for_submission(
            tim_sub["uuid"], requirements
        )["score"]
        self.assertIsNone(score)

        # Tim's workflow has enough grades.
        self.assertIsNotNone(PeerWorkflow.objects.get(student_id=tim["student_id"]).grading_completed_at)
Esempio n. 37
0
 def test_unexpected_workflow_get_errors_wrapped(self, data, mock_get):
     mock_get.side_effect = Exception("Kaboom!")
     submission = sub_api.create_submission(ITEM_1, "We talk TV!")
     workflow = workflow_api.create_workflow(submission["uuid"],
                                             data["steps"], ON_INIT_PARAMS)
     workflow_api.get_workflow_for_submission(workflow["uuid"], {})
Esempio n. 38
0
    def test_complex_peer_assessment_workflow(self):
        """
        Intended to mimic a more complicated scenario where people do not
        necessarily always finish their assessments.

        1) Angel submits
        2) Angel waits for Peer Assessments
        3) Bob submits and pulls Angel's submission but never reviews it.
        4) Sally submits
        5) Sally pulls Angel's Submission but never reviews it.
        6) Jim submits
        7) Jim also doesn't care about Angel and does not bother to review.
        8) Buffy comes along and she submits
        9) Buffy cares about Angel, but she won't get Angel's submission;
            it's held by Bob, Sally, and Jim.
        10) Buffy goes on to review Bob, Sally, and Jim, but needs two more.
        11) Xander comes along and submits.
        12) Xander means well, so Xander grades Bob, Sally, and Jim, but gets
            lazy and doesn't grade Buffy when her submission comes along.
        13) Buffy is waiting in the wings. She pulls Xander's submission and
            grades it.
        14) Spike submits.
        15) Spike reviews Bob, Sally, Jim, Buffy, and Xander.
        16) Buffy reviews Spike
        17) Willow comes along and submits
        18) Willow goes to grade, and should get Xander
        19) Xander comes back and gets Buffy's submission, and grades it.
        20) Buffy should now have a grade.
        """

        # Buffy should not have a score, because she has not evaluated enough
        # peer submissions.
        requirements = {
            "peer": {
                "must_grade": REQUIRED_GRADED,
                "must_be_graded_by": REQUIRED_GRADED_BY,
                }
        }

        # 1) Angel Submits
        angel_sub, angel = self._create_student_and_submission("Angel", "Angel's answer")

        # 2) Angel waits for peers
        sub = peer_api.get_submission_to_assess(angel, REQUIRED_GRADED_BY)
        self.assertIsNone(sub)
        # 3) Bob submits
        bob_sub, bob = self._create_student_and_submission("Bob", "Bob's answer")
        sub = peer_api.get_submission_to_assess(bob, REQUIRED_GRADED_BY)
        self.assertEquals(angel_sub["uuid"], sub["uuid"])

        # 4) Sally submits
        sally_sub, sally = self._create_student_and_submission("Sally", "Sally's answer")

        # 5) Sally pulls Angel's Submission but never reviews it.
        sub = peer_api.get_submission_to_assess(sally, REQUIRED_GRADED_BY)
        self.assertEquals(angel_sub["uuid"], sub["uuid"])

        # 6) Jim submits
        jim_sub, jim = self._create_student_and_submission("Jim", "Jim's answer")

        # 7) Jim also doesn't care about Angel and does not bother to review.
        sub = peer_api.get_submission_to_assess(jim, REQUIRED_GRADED_BY)
        self.assertEquals(angel_sub["uuid"], sub["uuid"])

        # 8) Buffy comes along and she submits
        buffy_sub, buffy = self._create_student_and_submission("Buffy", "Buffy's answer")

        # 9) Buffy cares about Angel, but she won't get Angel's submission;
        # it's held by Bob, Sally, and Jim.
        sub = peer_api.get_submission_to_assess(buffy, REQUIRED_GRADED_BY)
        self.assertEquals(bob_sub["uuid"], sub["uuid"])

        # 10) Buffy goes on to review Bob, Sally, and Jim, but needs two more.
        peer_api.create_assessment(
            sub["uuid"], buffy["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )
        sub = peer_api.get_submission_to_assess(buffy, REQUIRED_GRADED_BY)
        self.assertEquals(sally_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], buffy["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )
        sub = peer_api.get_submission_to_assess(buffy, REQUIRED_GRADED_BY)
        self.assertEquals(jim_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], buffy["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,

        )
        sub = peer_api.get_submission_to_assess(buffy, REQUIRED_GRADED_BY)
        self.assertIsNone(sub)

        # 11) Xander comes along and submits.
        xander_sub, xander = self._create_student_and_submission("Xander", "Xander's answer")

        # 12) Xander means well, so Xander grades Bob, Sally, and Jim, but gets
        # lazy and doesn't grade Buffy when her submission comes along.
        sub = peer_api.get_submission_to_assess(xander, REQUIRED_GRADED_BY)
        self.assertEquals(bob_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], xander["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )
        sub = peer_api.get_submission_to_assess(xander, REQUIRED_GRADED_BY)
        self.assertEquals(sally_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], xander["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )
        sub = peer_api.get_submission_to_assess(xander, REQUIRED_GRADED_BY)
        self.assertEquals(jim_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], xander["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        # Tim has met the critera, and should now have a score.
        # We patch the call to `self_api.is_complete()` simulate having completed a self-assessment.
        # TODO: currently, we need to import `self_api` within the `_is_self_complete` method
        # to avoid circular imports.  This means we can't patch self_api directly.
        from openassessment.workflow.models import AssessmentWorkflow
        with patch.object(AssessmentWorkflow, '_is_self_complete') as mock_complete:
            mock_complete.return_value = True
            score = workflow_api.get_workflow_for_submission(sub["uuid"], requirements)["score"]

        # 13) Buffy is waiting in the wings. She pulls Xander's submission and
        # grades it.
        sub = peer_api.get_submission_to_assess(buffy, REQUIRED_GRADED_BY)
        self.assertEquals(xander_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], buffy["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        # 14) Spike submits.
        spike_sub, spike = self._create_student_and_submission("Spike", "Spike's answer")

        # 15) Spike reviews Bob, Sally, Jim, Buffy, and Xander.
        sub = peer_api.get_submission_to_assess(spike, REQUIRED_GRADED_BY)
        self.assertEquals(bob_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], spike["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,

        )
        sub = peer_api.get_submission_to_assess(spike, REQUIRED_GRADED_BY)
        self.assertEquals(sally_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], spike["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )
        sub = peer_api.get_submission_to_assess(spike, REQUIRED_GRADED_BY)
        self.assertEquals(jim_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], spike["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )
        sub = peer_api.get_submission_to_assess(spike, REQUIRED_GRADED_BY)
        self.assertEquals(buffy_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], spike["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )
        sub = peer_api.get_submission_to_assess(spike, REQUIRED_GRADED_BY)
        self.assertEquals(xander_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], spike["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        # 16) Buffy reviews Spike
        sub = peer_api.get_submission_to_assess(buffy, REQUIRED_GRADED_BY)
        self.assertEquals(spike_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], buffy["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        # 17) Willow comes along and submits
        willow_sub, willow = self._create_student_and_submission("Willow", "Willow's answer")

        # 18) Willow goes to grade, and should get Buffy
        sub = peer_api.get_submission_to_assess(willow, REQUIRED_GRADED_BY)
        self.assertEquals(buffy_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], willow["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        # 19) Xander comes back and gets Buffy's submission, and grades it.
        sub = peer_api.get_submission_to_assess(xander, REQUIRED_GRADED_BY)
        self.assertEquals(buffy_sub["uuid"], sub["uuid"])
        peer_api.create_assessment(
            sub["uuid"], xander["student_id"], ASSESSMENT_DICT, RUBRIC_DICT,
            REQUIRED_GRADED_BY,
        )

        # 20) Buffy should now have a grade.
        requirements = {
            'must_grade': REQUIRED_GRADED,
            'must_be_graded_by': REQUIRED_GRADED_BY
        }
        self.assertTrue(peer_api.is_complete(buffy_sub["uuid"], requirements))
Esempio n. 39
0
 def test_unexpected_workflow_get_errors_wrapped(self, mock_get):
     mock_get.side_effect = Exception("Kaboom!")
     submission = sub_api.create_submission(ITEM_1, "We talk TV!")
     workflow = workflow_api.create_workflow(submission["uuid"])
     workflow_api.get_workflow_for_submission(workflow["uuid"], REQUIREMENTS)