diff --git a/lms/djangoapps/grades/new/course_grade.py b/lms/djangoapps/grades/new/course_grade.py index d9f2837330..003f03a02f 100644 --- a/lms/djangoapps/grades/new/course_grade.py +++ b/lms/djangoapps/grades/new/course_grade.py @@ -155,7 +155,7 @@ class CourseGrade(object): all scored problems that are children of the chosen location. """ if location in self.locations_to_weighted_scores: - score = self.locations_to_weighted_scores[location] + score, _ = self.locations_to_weighted_scores[location] return score.earned, score.possible children = self.course_structure.get_children(location) earned = 0.0 diff --git a/lms/djangoapps/grades/tests/test_grades.py b/lms/djangoapps/grades/tests/test_grades.py index ce6bf22899..f609098b43 100644 --- a/lms/djangoapps/grades/tests/test_grades.py +++ b/lms/djangoapps/grades/tests/test_grades.py @@ -2,14 +2,10 @@ Test grade calculation. """ -import ddt -from django.conf import settings from django.http import Http404 -from django.test import TestCase -from mock import patch, MagicMock +from mock import patch from nose.plugins.attrib import attr from opaque_keys.edx.locations import SlashSeparatedCourseKey -from opaque_keys.edx.locator import CourseLocator, BlockUsageLocator from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory from courseware.module_render import get_module @@ -18,7 +14,6 @@ from courseware.tests.helpers import ( LoginEnrollmentTestCase, get_request_for_user ) -from lms.djangoapps.course_blocks.api import get_course_blocks from student.tests.factories import UserFactory from student.models import CourseEnrollment from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory @@ -27,8 +22,7 @@ from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from .. import course_grades from ..course_grades import summary as grades_summary from ..module_grades import get_module_score -from ..new.course_grade import CourseGrade, CourseGradeFactory -from ..new.subsection_grade import SubsectionGradeFactory +from ..new.course_grade import CourseGradeFactory def _grade_with_errors(student, course): @@ -146,7 +140,7 @@ class TestGradeIteration(SharedModuleStoreTestCase): return students_to_gradesets, students_to_errors -class TestProgressSummary(TestCase): +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 @@ -161,114 +155,78 @@ class TestProgressSummary(TestCase): (2/5) (3/5) (0/1) - (1/3) - (3/10) """ - # Tell Django to clean out all databases, not just default - multi_db = True + @classmethod + def setUpClass(cls): + super(TestScoreForModule, cls).setUpClass() + cls.course = CourseFactory.create() + 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") - def setUp(self): - super(TestProgressSummary, self).setUp() - self.course_key = CourseLocator( - org='some_org', - course='some_course', - run='some_run' - ) - self.loc_a = self.create_location('chapter', 'a') - self.loc_b = self.create_location('section', 'b') - self.loc_c = self.create_location('section', 'c') - self.loc_d = self.create_location('vertical', 'd') - self.loc_e = self.create_location('vertical', 'e') - self.loc_f = self.create_location('vertical', 'f') - self.loc_g = self.create_location('vertical', 'g') - self.loc_h = self.create_location('problem', 'h') - self.loc_i = self.create_location('problem', 'i') - self.loc_j = self.create_location('problem', 'j') - self.loc_k = self.create_location('html', 'k') - self.loc_l = self.create_location('problem', 'l') - self.loc_m = self.create_location('html', 'm') - self.loc_n = self.create_location('problem', 'n') + cls.request = get_request_for_user(UserFactory()) + CourseEnrollment.enroll(cls.request.user, cls.course.id) - weighted_scores = { - self.loc_h: self.create_score(2, 5), - self.loc_i: self.create_score(3, 5), - self.loc_j: self.create_score(0, 1), - self.loc_l: self.create_score(1, 3), - self.loc_n: self.create_score(3, 10), - } - locations_to_scored_children = { - self.loc_a: [self.loc_h, self.loc_i, self.loc_j, self.loc_l, self.loc_n], - self.loc_b: [self.loc_h, self.loc_i, self.loc_j, self.loc_l], - self.loc_c: [self.loc_n], - self.loc_d: [self.loc_h, self.loc_i], - self.loc_e: [self.loc_j, self.loc_l], - self.loc_f: [], - self.loc_g: [self.loc_n], - self.loc_k: [], - self.loc_m: [], - } + 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) - course_structure = MagicMock() - course_structure.get_children = lambda location: locations_to_scored_children[location] - self.course_grade = CourseGrade(student=None, course=None, course_structure=course_structure) - self.course_grade.locations_to_weighted_scores = weighted_scores - - def create_score(self, earned, possible): - """ - Create a new mock Score object with specified earned and possible values - """ - score = MagicMock() - score.possible = possible - score.earned = earned - return score - - def create_location(self, block_type, block_id): - """ - Create a new BlockUsageLocation with the given type and ID. - """ - return BlockUsageLocator( - course_key=self.course_key, block_type=block_type, block_id=block_id - ) + cls.course_grade = CourseGradeFactory(cls.request.user).create(cls.course) def test_score_chapter(self): - earned, possible = self.course_grade.score_for_module(self.loc_a) + earned, possible = self.course_grade.score_for_module(self.a.location) self.assertEqual(earned, 9) self.assertEqual(possible, 24) def test_score_section_many_leaves(self): - earned, possible = self.course_grade.score_for_module(self.loc_b) + earned, possible = self.course_grade.score_for_module(self.b.location) self.assertEqual(earned, 6) self.assertEqual(possible, 14) def test_score_section_one_leaf(self): - earned, possible = self.course_grade.score_for_module(self.loc_c) + earned, possible = self.course_grade.score_for_module(self.c.location) self.assertEqual(earned, 3) self.assertEqual(possible, 10) def test_score_vertical_two_leaves(self): - earned, possible = self.course_grade.score_for_module(self.loc_d) + earned, possible = self.course_grade.score_for_module(self.d.location) self.assertEqual(earned, 5) self.assertEqual(possible, 10) def test_score_vertical_two_leaves_one_unscored(self): - earned, possible = self.course_grade.score_for_module(self.loc_e) + earned, possible = self.course_grade.score_for_module(self.e.location) self.assertEqual(earned, 1) self.assertEqual(possible, 4) def test_score_vertical_no_score(self): - earned, possible = self.course_grade.score_for_module(self.loc_f) + earned, possible = self.course_grade.score_for_module(self.f.location) self.assertEqual(earned, 0) self.assertEqual(possible, 0) def test_score_vertical_one_leaf(self): - earned, possible = self.course_grade.score_for_module(self.loc_g) + earned, possible = self.course_grade.score_for_module(self.g.location) self.assertEqual(earned, 3) self.assertEqual(possible, 10) def test_score_leaf(self): - earned, possible = self.course_grade.score_for_module(self.loc_h) + earned, possible = self.course_grade.score_for_module(self.h.location) self.assertEqual(earned, 2) self.assertEqual(possible, 5) def test_score_leaf_no_score(self): - earned, possible = self.course_grade.score_for_module(self.loc_m) + earned, possible = self.course_grade.score_for_module(self.m.location) self.assertEqual(earned, 0) self.assertEqual(possible, 0) @@ -464,7 +422,7 @@ class TestGetModuleScore(LoginEnrollmentTestCase, SharedModuleStoreTestCase): self.assertEqual(score, 1.0) -def answer_problem(course, request, problem, score=1): +def answer_problem(course, request, problem, score=1, max_value=1): """ Records a correct answer for the given problem. @@ -475,7 +433,7 @@ def answer_problem(course, request, problem, score=1): """ user = request.user - grade_dict = {'value': score, 'max_value': 1, 'user_id': user.id} + grade_dict = {'value': score, 'max_value': max_value, 'user_id': user.id} field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course.id, user,