Files
edx-platform/lms/djangoapps/grades/tests/test_course_grade.py
Michael Terry cb1bb7fa64 test: switch default test store to the split store
It's long past time that the default test modulestore was Split,
instead of Old Mongo. This commit switches the default store and
fixes some tests that now fail:
- Tests that didn't expect MFE to be enabled (because we don't
  enable MFE for Old Mongo) - opt out of MFE for those
- Tests that hardcoded old key string formats
- Lots of other random little differences

In many places, I didn't spend much time trying to figure out how to
properly fix the test, and instead just set the modulestore to Old
Mongo.

For those tests that I didn't spend time investigating, I've set
the modulestore to TEST_DATA_MONGO_AMNESTY_MODULESTORE - search for
that string to find further work.
2022-02-04 14:32:50 -05:00

158 lines
7.2 KiB
Python

# lint-amnesty, pylint: disable=missing-module-docstring
from unittest.mock import patch
import ddt
from crum import set_current_request
from django.conf import settings
from edx_toggles.toggles.testutils import override_waffle_switch
from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, SharedModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.student.tests.factories import UserFactory
from openedx.core.djangolib.testing.utils import get_mock_request
from ..config.waffle import ASSUME_ZERO_GRADE_IF_ABSENT, waffle_switch
from ..course_data import CourseData
from ..course_grade import ZeroCourseGrade
from ..course_grade_factory import CourseGradeFactory
from .base import GradeTestBase
from .utils import answer_problem
@patch.dict(settings.FEATURES, {'ASSUME_ZERO_GRADE_IF_ABSENT_FOR_ALL_TESTS': False})
@ddt.ddt
class ZeroGradeTest(GradeTestBase):
"""
Tests ZeroCourseGrade (and, implicitly, ZeroSubsectionGrade)
functionality.
"""
@ddt.data(True, False)
def test_zero(self, assume_zero_enabled):
"""
Creates a ZeroCourseGrade and ensures it's empty.
"""
with override_waffle_switch(waffle_switch(ASSUME_ZERO_GRADE_IF_ABSENT), active=assume_zero_enabled):
course_data = CourseData(self.request.user, structure=self.course_structure)
chapter_grades = ZeroCourseGrade(self.request.user, course_data).chapter_grades
for chapter in chapter_grades:
for section in chapter_grades[chapter]['sections']:
for score in section.problem_scores.values():
assert score.earned == 0
assert score.first_attempted is None
assert section.all_total.earned == 0
@ddt.data(True, False)
def test_zero_null_scores(self, assume_zero_enabled):
"""
Creates a zero course grade and ensures that null scores aren't included in the section problem scores.
"""
with override_waffle_switch(waffle_switch(ASSUME_ZERO_GRADE_IF_ABSENT), active=assume_zero_enabled):
with patch('lms.djangoapps.grades.subsection_grade.get_score', return_value=None):
course_data = CourseData(self.request.user, structure=self.course_structure)
chapter_grades = ZeroCourseGrade(self.request.user, course_data).chapter_grades
for chapter in chapter_grades:
assert {} != chapter_grades[chapter]['sections']
for section in chapter_grades[chapter]['sections']:
assert {} == section.problem_scores
class TestScoreForModule(SharedModuleStoreTestCase):
"""
Test the method that calculates the score for a given block based on the
cumulative scores of its children. This test class uses a hard-coded block
hierarchy with scores as follows:
a
+--------+--------+
b c
+--------------+-----------+ |
d e f g
+-----+ +-----+-----+ | |
h i j k l m n
(2/5) (3/5) (0/1) - (1/3) - (3/10)
"""
MODULESTORE = TEST_DATA_MONGO_AMNESTY_MODULESTORE
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.course = CourseFactory.create()
with cls.store.bulk_operations(cls.course.id):
cls.a = ItemFactory.create(parent=cls.course, category="chapter", display_name="a")
cls.b = ItemFactory.create(parent=cls.a, category="sequential", display_name="b")
cls.c = ItemFactory.create(parent=cls.a, category="sequential", display_name="c")
cls.d = ItemFactory.create(parent=cls.b, category="vertical", display_name="d")
cls.e = ItemFactory.create(parent=cls.b, category="vertical", display_name="e")
cls.f = ItemFactory.create(parent=cls.b, category="vertical", display_name="f")
cls.g = ItemFactory.create(parent=cls.c, category="vertical", display_name="g")
cls.h = ItemFactory.create(parent=cls.d, category="problem", display_name="h")
cls.i = ItemFactory.create(parent=cls.d, category="problem", display_name="i")
cls.j = ItemFactory.create(parent=cls.e, category="problem", display_name="j")
cls.k = ItemFactory.create(parent=cls.e, category="html", display_name="k")
cls.l = ItemFactory.create(parent=cls.e, category="problem", display_name="l")
cls.m = ItemFactory.create(parent=cls.f, category="html", display_name="m")
cls.n = ItemFactory.create(parent=cls.g, category="problem", display_name="n")
cls.request = get_mock_request(UserFactory())
CourseEnrollment.enroll(cls.request.user, cls.course.id)
answer_problem(cls.course, cls.request, cls.h, score=2, max_value=5)
answer_problem(cls.course, cls.request, cls.i, score=3, max_value=5)
answer_problem(cls.course, cls.request, cls.j, score=0, max_value=1)
answer_problem(cls.course, cls.request, cls.l, score=1, max_value=3)
answer_problem(cls.course, cls.request, cls.n, score=3, max_value=10)
cls.course_grade = CourseGradeFactory().read(cls.request.user, cls.course)
@classmethod
def tearDownClass(cls):
super().tearDownClass()
set_current_request(None)
def test_score_chapter(self):
earned, possible = self.course_grade.score_for_module(self.a.location)
assert earned == 9
assert possible == 24
def test_score_section_many_leaves(self):
earned, possible = self.course_grade.score_for_module(self.b.location)
assert earned == 6
assert possible == 14
def test_score_section_one_leaf(self):
earned, possible = self.course_grade.score_for_module(self.c.location)
assert earned == 3
assert possible == 10
def test_score_vertical_two_leaves(self):
earned, possible = self.course_grade.score_for_module(self.d.location)
assert earned == 5
assert possible == 10
def test_score_vertical_two_leaves_one_unscored(self):
earned, possible = self.course_grade.score_for_module(self.e.location)
assert earned == 1
assert possible == 4
def test_score_vertical_no_score(self):
earned, possible = self.course_grade.score_for_module(self.f.location)
assert earned == 0
assert possible == 0
def test_score_vertical_one_leaf(self):
earned, possible = self.course_grade.score_for_module(self.g.location)
assert earned == 3
assert possible == 10
def test_score_leaf(self):
earned, possible = self.course_grade.score_for_module(self.h.location)
assert earned == 2
assert possible == 5
def test_score_leaf_no_score(self):
earned, possible = self.course_grade.score_for_module(self.m.location)
assert earned == 0
assert possible == 0