Commit 1b6afb0b by Eric Fischer Committed by GitHub

Merge pull request #13482 from edx/hotfix/2016-09-15

Fix grade push back for non-components through LTI
parents f13f05b3 89750172
...@@ -147,7 +147,7 @@ class CourseGrade(object): ...@@ -147,7 +147,7 @@ class CourseGrade(object):
all scored problems that are children of the chosen location. all scored problems that are children of the chosen location.
""" """
if location in self.locations_to_weighted_scores: 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 return score.earned, score.possible
children = self.course_structure.get_children(location) children = self.course_structure.get_children(location)
earned = 0.0 earned = 0.0
......
...@@ -2,14 +2,10 @@ ...@@ -2,14 +2,10 @@
Test grade calculation. Test grade calculation.
""" """
import ddt
from django.conf import settings
from django.http import Http404 from django.http import Http404
from django.test import TestCase from mock import patch
from mock import patch, MagicMock
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from opaque_keys.edx.locations import SlashSeparatedCourseKey from opaque_keys.edx.locations import SlashSeparatedCourseKey
from opaque_keys.edx.locator import CourseLocator, BlockUsageLocator
from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
from courseware.module_render import get_module from courseware.module_render import get_module
...@@ -18,7 +14,6 @@ from courseware.tests.helpers import ( ...@@ -18,7 +14,6 @@ from courseware.tests.helpers import (
LoginEnrollmentTestCase, LoginEnrollmentTestCase,
get_request_for_user get_request_for_user
) )
from lms.djangoapps.course_blocks.api import get_course_blocks
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from student.models import CourseEnrollment from student.models import CourseEnrollment
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
...@@ -27,8 +22,7 @@ from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase ...@@ -27,8 +22,7 @@ from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
from .. import course_grades from .. import course_grades
from ..course_grades import summary as grades_summary from ..course_grades import summary as grades_summary
from ..module_grades import get_module_score from ..module_grades import get_module_score
from ..new.course_grade import CourseGrade, CourseGradeFactory from ..new.course_grade import CourseGradeFactory
from ..new.subsection_grade import SubsectionGradeFactory
def _grade_with_errors(student, course): def _grade_with_errors(student, course):
...@@ -146,7 +140,7 @@ class TestGradeIteration(SharedModuleStoreTestCase): ...@@ -146,7 +140,7 @@ class TestGradeIteration(SharedModuleStoreTestCase):
return students_to_gradesets, students_to_errors 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 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 cumulative scores of its children. This test class uses a hard-coded block
...@@ -161,114 +155,78 @@ class TestProgressSummary(TestCase): ...@@ -161,114 +155,78 @@ class TestProgressSummary(TestCase):
(2/5) (3/5) (0/1) - (1/3) - (3/10) (2/5) (3/5) (0/1) - (1/3) - (3/10)
""" """
# Tell Django to clean out all databases, not just default @classmethod
multi_db = True def setUpClass(cls):
super(TestScoreForModule, cls).setUpClass()
def setUp(self): cls.course = CourseFactory.create()
super(TestProgressSummary, self).setUp() cls.a = ItemFactory.create(parent=cls.course, category="chapter", display_name="a")
self.course_key = CourseLocator( cls.b = ItemFactory.create(parent=cls.a, category="sequential", display_name="b")
org='some_org', cls.c = ItemFactory.create(parent=cls.a, category="sequential", display_name="c")
course='some_course', cls.d = ItemFactory.create(parent=cls.b, category="vertical", display_name="d")
run='some_run' cls.e = ItemFactory.create(parent=cls.b, category="vertical", display_name="e")
) cls.f = ItemFactory.create(parent=cls.b, category="vertical", display_name="f")
self.loc_a = self.create_location('chapter', 'a') cls.g = ItemFactory.create(parent=cls.c, category="vertical", display_name="g")
self.loc_b = self.create_location('section', 'b') cls.h = ItemFactory.create(parent=cls.d, category="problem", display_name="h")
self.loc_c = self.create_location('section', 'c') cls.i = ItemFactory.create(parent=cls.d, category="problem", display_name="i")
self.loc_d = self.create_location('vertical', 'd') cls.j = ItemFactory.create(parent=cls.e, category="problem", display_name="j")
self.loc_e = self.create_location('vertical', 'e') cls.k = ItemFactory.create(parent=cls.e, category="html", display_name="k")
self.loc_f = self.create_location('vertical', 'f') cls.l = ItemFactory.create(parent=cls.e, category="problem", display_name="l")
self.loc_g = self.create_location('vertical', 'g') cls.m = ItemFactory.create(parent=cls.f, category="html", display_name="m")
self.loc_h = self.create_location('problem', 'h') cls.n = ItemFactory.create(parent=cls.g, category="problem", display_name="n")
self.loc_i = self.create_location('problem', 'i')
self.loc_j = self.create_location('problem', 'j') cls.request = get_request_for_user(UserFactory())
self.loc_k = self.create_location('html', 'k') CourseEnrollment.enroll(cls.request.user, cls.course.id)
self.loc_l = self.create_location('problem', 'l')
self.loc_m = self.create_location('html', 'm') answer_problem(cls.course, cls.request, cls.h, score=2, max_value=5)
self.loc_n = self.create_location('problem', 'n') 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)
weighted_scores = { answer_problem(cls.course, cls.request, cls.l, score=1, max_value=3)
self.loc_h: self.create_score(2, 5), answer_problem(cls.course, cls.request, cls.n, score=3, max_value=10)
self.loc_i: self.create_score(3, 5),
self.loc_j: self.create_score(0, 1), cls.course_grade = CourseGradeFactory(cls.request.user).create(cls.course)
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: [],
}
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
)
def test_score_chapter(self): 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(earned, 9)
self.assertEqual(possible, 24) self.assertEqual(possible, 24)
def test_score_section_many_leaves(self): 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(earned, 6)
self.assertEqual(possible, 14) self.assertEqual(possible, 14)
def test_score_section_one_leaf(self): 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(earned, 3)
self.assertEqual(possible, 10) self.assertEqual(possible, 10)
def test_score_vertical_two_leaves(self): 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(earned, 5)
self.assertEqual(possible, 10) self.assertEqual(possible, 10)
def test_score_vertical_two_leaves_one_unscored(self): 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(earned, 1)
self.assertEqual(possible, 4) self.assertEqual(possible, 4)
def test_score_vertical_no_score(self): 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(earned, 0)
self.assertEqual(possible, 0) self.assertEqual(possible, 0)
def test_score_vertical_one_leaf(self): 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(earned, 3)
self.assertEqual(possible, 10) self.assertEqual(possible, 10)
def test_score_leaf(self): 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(earned, 2)
self.assertEqual(possible, 5) self.assertEqual(possible, 5)
def test_score_leaf_no_score(self): 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(earned, 0)
self.assertEqual(possible, 0) self.assertEqual(possible, 0)
...@@ -453,7 +411,7 @@ class TestGetModuleScore(LoginEnrollmentTestCase, SharedModuleStoreTestCase): ...@@ -453,7 +411,7 @@ class TestGetModuleScore(LoginEnrollmentTestCase, SharedModuleStoreTestCase):
self.assertEqual(score, 1.0) 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. Records a correct answer for the given problem.
...@@ -464,7 +422,7 @@ def answer_problem(course, request, problem, score=1): ...@@ -464,7 +422,7 @@ def answer_problem(course, request, problem, score=1):
""" """
user = request.user 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( field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
course.id, course.id,
user, user,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment