Merge pull request #13487 from edx/release
Hotfix 2016-09-15 release to master
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user