test_spoc_gradebook.py 5.99 KB
Newer Older
1
"""
2
Tests of the instructor dashboard spoc gradebook
3 4 5
"""

from django.core.urlresolvers import reverse
6
from nose.plugins.attrib import attr
7
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
8
from student.tests.factories import UserFactory, CourseEnrollmentFactory, AdminFactory
9 10 11 12 13 14 15 16
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from capa.tests.response_xml_factory import StringResponseXMLFactory
from courseware.tests.factories import StudentModuleFactory
from xmodule.modulestore.django import modulestore


USER_COUNT = 11

Miles Steele committed
17

18
@attr('shard_1')
19
class TestGradebook(ModuleStoreTestCase):
20 21 22 23 24
    """
    Test functionality of the spoc gradebook. Sets up a course with assignments and
    students who've scored various scores on these assignments. Base class for further
    gradebook tests.
    """
25 26 27
    grading_policy = None

    def setUp(self):
28 29
        super(TestGradebook, self).setUp()

30 31 32
        instructor = AdminFactory.create()
        self.client.login(username=instructor.username, password='test')

33
        # remove the caches
34 35
        modulestore().request_cache = None
        modulestore().metadata_inheritance_cache_subsystem = None
36

37
        kwargs = {}
38
        if self.grading_policy is not None:
39
            kwargs['grading_policy'] = self.grading_policy
40

41
        self.course = CourseFactory.create(**kwargs)
42 43
        chapter = ItemFactory.create(
            parent_location=self.course.location,
44
            category="sequential",
45 46 47
        )
        section = ItemFactory.create(
            parent_location=chapter.location,
48
            category="sequential",
49 50 51
            metadata={'graded': True, 'format': 'Homework'}
        )

52
        self.users = [UserFactory.create() for _ in xrange(USER_COUNT)]
53 54 55 56

        for user in self.users:
            CourseEnrollmentFactory.create(user=user, course_id=self.course.id)

57 58
        for i in xrange(USER_COUNT - 1):
            category = "problem"
59 60
            item = ItemFactory.create(
                parent_location=section.location,
61
                category=category,
62 63 64 65 66 67 68 69 70 71
                data=StringResponseXMLFactory().build_xml(answer='foo'),
                metadata={'rerandomize': 'always'}
            )

            for j, user in enumerate(self.users):
                StudentModuleFactory.create(
                    grade=1 if i < j else 0,
                    max_grade=1,
                    student=user,
                    course_id=self.course.id,
72
                    module_state_key=item.location
73 74
                )

75
        self.response = self.client.get(reverse(
76
            'spoc_gradebook',
77 78
            args=(self.course.id.to_deprecated_string(),)
        ))
79 80 81 82

    def test_response_code(self):
        self.assertEquals(self.response.status_code, 200)

Miles Steele committed
83

84
@attr('shard_1')
85
class TestDefaultGradingPolicy(TestGradebook):
86 87 88 89
    """
    Tests that the grading policy is properly applied for all users in the course
    Uses the default policy (50% passing rate)
    """
90 91
    def test_all_users_listed(self):
        for user in self.users:
92
            self.assertIn(user.username, unicode(self.response.content, 'utf-8'))
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108

    def test_default_policy(self):
        # Default >= 50% passes, so Users 5-10 should be passing for Homework 1 [6]
        # One use at the top of the page [1]
        self.assertEquals(7, self.response.content.count('grade_Pass'))

        # Users 1-5 attempted Homework 1 (and get Fs) [4]
        # Users 1-10 attempted any homework (and get Fs) [10]
        # Users 4-10 scored enough to not get rounded to 0 for the class (and get Fs) [7]
        # One use at top of the page [1]
        self.assertEquals(22, self.response.content.count('grade_F'))

        # All other grades are None [29 categories * 11 users - 27 non-empty grades = 292]
        # One use at the top of the page [1]
        self.assertEquals(293, self.response.content.count('grade_None'))

Miles Steele committed
109

110
@attr('shard_1')
111
class TestLetterCutoffPolicy(TestGradebook):
112 113 114 115
    """
    Tests advanced grading policy (with letter grade cutoffs). Includes tests of
    UX display (color, etc).
    """
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
    grading_policy = {
        "GRADER": [
            {
                "type": "Homework",
                "min_count": 1,
                "drop_count": 0,
                "short_label": "HW",
                "weight": 1
            },
        ],
        "GRADE_CUTOFFS": {
            'A': .9,
            'B': .8,
            'C': .7,
            'D': .6,
        }
    }

    def test_styles(self):

        self.assertIn("grade_A {color:green;}", self.response.content)
        self.assertIn("grade_B {color:Chocolate;}", self.response.content)
        self.assertIn("grade_C {color:DarkSlateGray;}", self.response.content)
        self.assertIn("grade_D {color:DarkSlateGray;}", self.response.content)

    def test_assigned_grades(self):
        print self.response.content
        # Users 9-10 have >= 90% on Homeworks [2]
        # Users 9-10 have >= 90% on the class [2]
        # One use at the top of the page [1]
        self.assertEquals(5, self.response.content.count('grade_A'))

        # User 8 has 80 <= Homeworks < 90 [1]
        # User 8 has 80 <= class < 90 [1]
        # One use at the top of the page [1]
        self.assertEquals(3, self.response.content.count('grade_B'))

        # User 7 has 70 <= Homeworks < 80 [1]
        # User 7 has 70 <= class < 80 [1]
        # One use at the top of the page [1]
        self.assertEquals(3, self.response.content.count('grade_C'))

        # User 6 has 60 <= Homeworks < 70 [1]
        # User 6 has 60 <= class < 70 [1]
        # One use at the top of the page [1]
        self.assertEquals(3, self.response.content.count('grade_C'))

        # Users 1-5 have 60% > grades > 0 on Homeworks [5]
        # Users 1-5 have 60% > grades > 0 on the class [5]
        # One use at top of the page [1]
        self.assertEquals(11, self.response.content.count('grade_F'))

        # User 0 has 0 on Homeworks [1]
        # User 0 has 0 on the class [1]
        # One use at the top of the page [1]
171
        self.assertEquals(3, self.response.content.count('grade_None'))