Exemplo n.º 1
0
 def test_grades_view_oauth2(self):
     """
     Test the grades view using OAuth2 Authentication
     """
     self.users_and_problem_setup()
     CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id)
     query_string = urllib.urlencode({'course_id': self.course.id, 'username': self.user.username})
     url = '/api/server/mobile/v1/users/courses/grades/?{}'.format(query_string)
     self.request.user = self.user
     answer_problem(self.course, self.request, self.problem, score=1, max_value=1)
     # Try with no authentication:
     self.client.logout()
     response = self.client.get(url)
     self.assertEqual(response.status_code, 401)
     user_grade = 0.8
     StudentGradebook.objects.update_or_create(
         user=self.user,
         course_id=self.course.id,
         defaults={
             'grade': user_grade,
             'proforma_grade': 1,
             'is_passed': True,
         }
     )
     # Now, try with a valid token header:
     token = self.create_oauth2_token(self.user)
     response = self.client.get(url, HTTP_AUTHORIZATION="Bearer {0}".format(token))
     self.assertEqual(response.status_code, 200)
     self.assertEqual(response.data['course_grade'], user_grade)
Exemplo n.º 2
0
 def test_orphaned_xblock(self):
     with patch(
             'lms.djangoapps.gating.signals.gating_api.evaluate_prerequisite'
     ) as mock_handler:
         self.assertFalse(mock_handler.called)
         answer_problem(self.course, self.request, self.orphan, 1, 1)
         self.assertFalse(mock_handler.called)
Exemplo n.º 3
0
    def test_invalid_min_score(self, earned, max_possible, result):
        self.setup_gating_milestone(None)

        answer_problem(self.course, self.request, self.gating_prob1, earned,
                       max_possible)
        self.verify_user_has_prereq_milestone(self.user,
                                              expected_has_milestone=result)
Exemplo n.º 4
0
    def test_ungating_when_fulfilled(self, earned, max_possible, result):
        self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=False)
        self.assert_access_to_gated_content(self.non_staff_user, expected_access=False)

        answer_problem(self.course, self.request, self.gating_prob1, earned, max_possible)

        self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=result)
        self.assert_access_to_gated_content(self.non_staff_user, expected_access=result)
Exemplo n.º 5
0
    def test_ungating_when_fulfilled(self, earned, max_possible, result):
        self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=False)
        self.assert_access_to_gated_content(self.non_staff_user)

        answer_problem(self.course, self.request, self.gating_prob1, earned, max_possible)

        self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=result)
        self.assert_access_to_gated_content(self.non_staff_user)
Exemplo n.º 6
0
    def test_ungating_when_fulfilled(self, earned, max_possible, result):
        self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=False)
        self.assert_access_to_gated_content(self.non_staff_user)
        with completion_waffle.waffle().override(completion_waffle.ENABLE_COMPLETION_TRACKING, True):
            answer_problem(self.course, self.request, self.gating_prob1, earned, max_possible)

            self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=result)
            self.assert_access_to_gated_content(self.non_staff_user)
Exemplo n.º 7
0
    def test_ungating_when_fulfilled(self, earned, max_possible, result):
        self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=False)
        self.assert_access_to_gated_content(self.non_staff_user)
        with override_waffle_switch(ENABLE_COMPLETION_TRACKING_SWITCH, True):
            answer_problem(self.course, self.request, self.gating_prob1, earned, max_possible)

            self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=result)
            self.assert_access_to_gated_content(self.non_staff_user)
Exemplo n.º 8
0
    def test_min_score_achieved(self, earned, max_possible, result):
        self.setup_gating_milestone(50)

        self.verify_user_has_prereq_milestone(self.user, expected_has_milestone=False)
        self.verify_access_to_gated_content(self.user, expected_access=False)

        answer_problem(self.course, self.request, self.gating_prob1, earned, max_possible)

        self.verify_user_has_prereq_milestone(self.user, expected_has_milestone=result)
        self.verify_access_to_gated_content(self.user, expected_access=result)
Exemplo n.º 9
0
 def test_delete_student_state(self, _crum_mock):
     problem_location = self.problem.location
     self._get_subsection_grade_and_verify(0, 1, 0, 1)
     answer_problem(course=self.course, request=self.request, problem=self.problem, score=1, max_value=1)
     self._get_subsection_grade_and_verify(1, 1, 1, 1)
     # Delete student state using the instructor dash
     reset_student_attempts(
         self.course.id,
         self.user,
         problem_location,
         requesting_user=self.instructor,
         delete_module=True,
     )
     # Verify that the student's grades are reset
     self._get_subsection_grade_and_verify(0, 1, 0, 1)
Exemplo n.º 10
0
    def test_gated_content_always_in_grades(self):
        # start with a grade from a non-gated subsection
        answer_problem(self.course, self.request, self.prob3, 10, 10)

        # verify gated status and overall course grade percentage
        self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=False)
        self.assert_access_to_gated_content(self.non_staff_user, expected_access=False)
        self.assert_course_grade(self.non_staff_user, .33)

        # fulfill the gated requirements
        answer_problem(self.course, self.request, self.gating_prob1, 10, 10)

        # verify gated status and overall course grade percentage
        self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=True)
        self.assert_access_to_gated_content(self.non_staff_user, expected_access=True)
        self.assert_course_grade(self.non_staff_user, .67)
Exemplo n.º 11
0
    def test_gated_content_always_in_grades(self):
        # start with a grade from a non-gated subsection
        answer_problem(self.course, self.request, self.prob3, 10, 10)

        # verify gated status and overall course grade percentage
        self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=False)
        self.assert_access_to_gated_content(self.non_staff_user)
        self.assert_course_grade(self.non_staff_user, .33)

        # fulfill the gated requirements
        answer_problem(self.course, self.request, self.gating_prob1, 10, 10)

        # verify gated status and overall course grade percentage
        self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=True)
        self.assert_access_to_gated_content(self.non_staff_user)
        self.assert_course_grade(self.non_staff_user, .67)
Exemplo n.º 12
0
    def test_gated_content_always_in_grades(self):
        with override_waffle_switch(completion_waffle.ENABLE_COMPLETION_TRACKING_SWITCH, True):
            # start with a grade from a non-gated subsection
            answer_problem(self.course, self.request, self.prob3, 10, 10)

            # verify gated status and overall course grade percentage
            self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=False)
            self.assert_access_to_gated_content(self.non_staff_user)
            self.assert_course_grade(self.non_staff_user, .33)

            # fulfill the gated requirements
            answer_problem(self.course, self.request, self.gating_prob1, 10, 10)

            # verify gated status and overall course grade percentage
            self.assert_user_has_prereq_milestone(self.non_staff_user, expected_has_milestone=True)
            self.assert_access_to_gated_content(self.non_staff_user)
            self.assert_course_grade(self.non_staff_user, .67)
Exemplo n.º 13
0
    def test_course_grade_considers_subsection_grade_visibility(
            self, is_staff, expected_percent):
        """
        Verify that the grade & is_passing info we send out is for visible grades only.

        Assumes that grading policy is the default one (search for DEFAULT_GRADING_POLICY).
        """
        if is_staff:
            self.switch_to_staff()
        CourseEnrollment.enroll(self.user, self.course.id)

        tomorrow = now() + timedelta(days=1)
        with self.store.bulk_operations(self.course.id):
            never = self.add_subsection_with_problem(format='Homework',
                                                     show_correctness='never')
            always = self.add_subsection_with_problem(
                format='Midterm Exam', show_correctness='always')
            past_due = self.add_subsection_with_problem(
                format='Final Exam', show_correctness='past_due', due=tomorrow)

        answer_problem(self.course, get_mock_request(self.user), never)
        answer_problem(self.course, get_mock_request(self.user), always)
        answer_problem(self.course, get_mock_request(self.user), past_due)

        # First, confirm the grade in the database - it should never change based on user state.
        # This is midterm and final and a single problem added together.
        assert CourseGradeFactory().read(self.user,
                                         self.course).percent == 0.72

        response = self.client.get(self.url)
        assert response.status_code == 200
        assert response.data['course_grade']['percent'] == expected_percent
        assert response.data['course_grade']['is_passing'] == (expected_percent
                                                               >= 0.5)
Exemplo n.º 14
0
    def test_user_course_grades_and_course_average(self):
        self.users_and_problem_setup()

        # Just two users for now
        CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id)
        CourseEnrollmentFactory.create(user=self.user2, course_id=self.course.id)

        # Ensure the the baseline score and average are 0
        self.login_and_enroll()
        response = self.api_response(
            expected_response_code=None,
            data={'course_id': unicode(self.course.id), 'username': self.user.username}
        )
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.data['course_grade'], 0)
        self.assertEqual(response.data['course_average_grade'], 0)

        # Answer some problems
        self.request.user = self.user
        answer_problem(self.course, self.request, self.problem, score=1, max_value=1)
        self.request.user = self.user2
        answer_problem(self.course, self.request, self.problem, score=1, max_value=5)

        # Calculate the expected course average
        user_grade = 0.1
        StudentGradebook.objects.update_or_create(
            user=self.user,
            course_id=self.course.id,
            defaults={
                'grade': user_grade,
                'proforma_grade': 1,
                'is_passed': True,
            }
        )
        user2_grade = 0.3
        StudentGradebook.objects.update_or_create(
            user=self.user2,
            course_id=self.course.id,
            defaults={
                'grade': user2_grade,
                'proforma_grade': 1,
                'is_passed': True,
            }
        )
        course_avg_grade = (user_grade + user2_grade) / float(2)
        self.assertTrue(course_avg_grade > 0)

        self.login_and_enroll()
        response = self.api_response(
            expected_response_code=None,
            data={'course_id': unicode(self.course.id), 'username': self.user.username}
        )

        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.data['course_grade'], user_grade)
        self.assertEqual(response.data['course_average_grade'], course_avg_grade)

        # Enroll another user, with a higher grade,
        # and check that the average grade is updated
        self.request.user = self.user3
        CourseEnrollmentFactory.create(user=self.user3, course_id=self.course.id)
        answer_problem(self.course, self.request, self.problem, score=10, max_value=1)
        user3_grade = 0.5
        StudentGradebook.objects.update_or_create(
            user=self.user3,
            course_id=self.course.id,
            defaults={
                'grade': user3_grade,
                'proforma_grade': 1,
                'is_passed': True,
            }
        )
        new_course_avg_grade = (user_grade + user2_grade + user3_grade) / float(3)

        response = self.api_response(
            expected_response_code=None,
            data={'course_id': unicode(self.course.id), 'username': self.user.username}
        )
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.data['course_grade'], user_grade)
        self.assertEqual(response.data['course_average_grade'], new_course_avg_grade)
        self.assertTrue(new_course_avg_grade > course_avg_grade)
Exemplo n.º 15
0
    def setUp(self):
        super(TestExpectedGrading, self).setUp()
        self.course = CourseFactory.create()
        with self.store.bulk_operations(self.course.id):
            self.a = ItemFactory.create(parent=self.course,
                                        category="chapter",
                                        display_name="a")
            metadata = {'format': 'Homework', 'graded': True}
            self.b = ItemFactory.create(parent=self.a,
                                        category="sequential",
                                        display_name="b",
                                        metadata=metadata)
            self.c = ItemFactory.create(parent=self.a,
                                        category="sequential",
                                        display_name="c",
                                        metadata=metadata)
            self.d = ItemFactory.create(parent=self.b,
                                        category="vertical",
                                        display_name="d")
            self.e = ItemFactory.create(parent=self.b,
                                        category="vertical",
                                        display_name="e")
            self.f = ItemFactory.create(parent=self.b,
                                        category="vertical",
                                        display_name="f")
            self.g = ItemFactory.create(parent=self.c,
                                        category="vertical",
                                        display_name="g")
            metadata.pop('graded')
            self.h = ItemFactory.create(parent=self.d,
                                        category="problem",
                                        display_name="h",
                                        metadata=metadata)
            self.i = ItemFactory.create(parent=self.d,
                                        category="problem",
                                        display_name="i",
                                        metadata=metadata)
            self.j = ItemFactory.create(parent=self.e,
                                        category="problem",
                                        display_name="j",
                                        metadata=metadata)
            self.k = ItemFactory.create(parent=self.e,
                                        category="html",
                                        display_name="k")
            self.l = ItemFactory.create(parent=self.e,
                                        category="problem",
                                        display_name="l",
                                        metadata=metadata)
            self.m = ItemFactory.create(parent=self.f,
                                        category="html",
                                        display_name="m")
            self.n = ItemFactory.create(parent=self.g,
                                        category="problem",
                                        display_name="n",
                                        metadata=metadata)

        grading_policy = {
            "GRADER": [
                {
                    "type": "Homework",
                    "min_count": 1,
                    "drop_count": 0,
                    "short_label": "HW",
                    "weight": 1.0,
                },
            ],
            "GRADE_CUTOFFS": {
                "Pass": 0.5,
            },
        }

        self.course.set_grading_policy(grading_policy)
        self.store.update_item(self.course, 0)
        self.course = self.store.get_course(self.course.id)

        self.request = get_mock_request(UserFactory())
        CourseEnrollment.enroll(self.request.user, self.course.id)

        answer_problem(self.course, self.request, self.h, score=2, max_value=5)
        answer_problem(self.course, self.request, self.i, score=3, max_value=5)
        answer_problem(self.course, self.request, self.j, score=0, max_value=1)
        answer_problem(self.course, self.request, self.l, score=1, max_value=3)
        answer_problem(self.course,
                       self.request,
                       self.n,
                       score=6,
                       max_value=10)
Exemplo n.º 16
0
    def _build_from_tree(self, tree):
        """
        Builds course from tree. Tree is stored in dict in a view like this:
        {
            "SectionName1":{
                "SubsectionName11_or_smth_else":("assignment_category" if graded, {
                    "BlockName111":(weight or None(means 'html'), {
                        "ProblemOrHtmlName":(earn, max)
                    }
                })
            }
        }
        """
        course = self.course
        request = self.request
        self.course_tree = {}
        to_answer = []
        for section_name, section_tree in tree.iteritems():
            current_section = ItemFactory.create(parent=course,
                                                 category="chapter",
                                                 display_name=section_name)
            self.course_tree[section_name] = current_section
            for subsection_name, subsection_pair in section_tree.iteritems():
                assignment_category, subsection_tree = subsection_pair
                current_subsection = ItemFactory.create(
                    parent=current_section,
                    category="sequential",
                    display_name=subsection_name,
                    graded=assignment_category is not None,
                    format=assignment_category or "")
                self.course_tree[subsection_name] = current_subsection
                for unit_name, unit_pair in subsection_tree.iteritems():
                    weight, unit_tree = unit_pair
                    metadata = {} if (weight is None) else {"weight": weight}
                    current_unit = ItemFactory.create(
                        parent=current_subsection,
                        category="vertical",
                        display_name=unit_name,
                        metadata=metadata)
                    self.course_tree[unit_name] = current_unit
                    for problem_name, problem_pair in unit_tree.iteritems():
                        earned, max_ = problem_pair

                        kwargs = {
                            "parent": current_unit,
                            "display_name": problem_name,
                            "category": "html" if max_ is None else "problem"
                        }
                        if assignment_category and not (max is None):
                            kwargs["format"] = assignment_category
                        current_problem = ItemFactory.create(**kwargs)
                        if not (max_ is None):
                            to_answer.append((current_problem, (earned, max_)))
                        self.course_tree[problem_name] = current_problem
        # Somehow 'answer_problem' must be after course building, otherwise
        # items not created
        for problem, pair in to_answer:
            earned, max_ = pair
            answer_problem(course,
                           request,
                           problem,
                           score=earned,
                           max_value=max_)
Exemplo n.º 17
0
    def test_invalid_min_score(self, earned, max_possible, result, mock_log):
        self.setup_gating_milestone(None)

        answer_problem(self.course, self.request, self.gating_prob1, earned, max_possible)
        self.verify_user_has_prereq_milestone(self.user, expected_has_milestone=result)
        self.assertTrue(mock_log.called)
Exemplo n.º 18
0
 def test_orphaned_xblock(self):
     with patch('lms.djangoapps.gating.signals.gating_api.evaluate_prerequisite') as mock_handler:
         self.assertFalse(mock_handler.called)
         answer_problem(self.course, self.request, self.orphan, 1, 1)
         self.assertFalse(mock_handler.called)
Exemplo n.º 19
0
 def test_no_prerequisites(self, mock_milestones):
     answer_problem(self.course, self.request, self.gating_prob1, 1, 1)
     self.assertFalse(mock_milestones.called)
Exemplo n.º 20
0
 def test_no_gated_content(self, mock_milestones):
     gating_api.add_prerequisite(self.course.id, self.seq1.location)
     answer_problem(self.course, self.request, self.gating_prob1, 1, 1)
     self.assertFalse(mock_milestones.called)