add grading policy hash to transformer
This commit is contained in:
@@ -7,9 +7,11 @@ import pytz
|
||||
import random
|
||||
|
||||
import ddt
|
||||
from copy import deepcopy
|
||||
|
||||
from student.tests.factories import UserFactory
|
||||
from xmodule.modulestore import ModuleStoreEnum
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import check_mongo_calls
|
||||
|
||||
@@ -39,6 +41,27 @@ class GradesTransformerTestCase(CourseStructureTestCase):
|
||||
self.student = UserFactory.create(is_staff=False, username=u'test_student', password=password)
|
||||
self.client.login(username=self.student.username, password=password)
|
||||
|
||||
def _update_course_grading_policy(self, course, grading_policy):
|
||||
"""
|
||||
Helper to update a course's grading policy in the modulestore.
|
||||
"""
|
||||
course.set_grading_policy(grading_policy)
|
||||
modulestore().update_item(course, self.user.id)
|
||||
|
||||
def _validate_grading_policy_hash(self, course_location, grading_policy_hash):
|
||||
"""
|
||||
Helper to retrieve the course at the given course_location and
|
||||
assert that its hashed grading policy (from the grades transformer)
|
||||
is as expected.
|
||||
"""
|
||||
block_structure = get_course_blocks(self.student, course_location, self.transformers)
|
||||
self.assert_collected_transformer_block_fields(
|
||||
block_structure,
|
||||
course_location,
|
||||
self.TRANSFORMER_CLASS_TO_TEST,
|
||||
grading_policy_hash=grading_policy_hash,
|
||||
)
|
||||
|
||||
def assert_collected_xblock_fields(self, block_structure, usage_key, **expectations):
|
||||
"""
|
||||
Given a block structure, a block usage key, and a list of keyword
|
||||
@@ -330,6 +353,38 @@ class GradesTransformerTestCase(CourseStructureTestCase):
|
||||
block_structure = get_course_blocks(self.student, blocks[u'course'].location, self.transformers)
|
||||
self.assertIsNotNone(block_structure.get_xblock_field(blocks[u'course'].location, u'course_version'))
|
||||
|
||||
def test_grading_policy_collected(self):
|
||||
# the calculated hash of the original and updated grading policies of the test course
|
||||
original_grading_policy_hash = u'ChVp0lHGQGCevD0t4njna/C44zQ='
|
||||
updated_grading_policy_hash = u'TsbX04qWOy1WRnC0NHy+94upPd4='
|
||||
|
||||
blocks = self.build_course_with_problems()
|
||||
course_block = blocks[u'course']
|
||||
self._validate_grading_policy_hash(
|
||||
course_block.location,
|
||||
original_grading_policy_hash
|
||||
)
|
||||
|
||||
# make sure the hash changes when the course grading policy is edited
|
||||
grading_policy_with_updates = course_block.grading_policy
|
||||
original_grading_policy = deepcopy(grading_policy_with_updates)
|
||||
for section in grading_policy_with_updates['GRADER']:
|
||||
self.assertNotEqual(section['weight'], 0.25)
|
||||
section['weight'] = 0.25
|
||||
|
||||
self._update_course_grading_policy(course_block, grading_policy_with_updates)
|
||||
self._validate_grading_policy_hash(
|
||||
course_block.location,
|
||||
updated_grading_policy_hash
|
||||
)
|
||||
|
||||
# reset the grading policy and ensure the hash matches the original
|
||||
self._update_course_grading_policy(course_block, original_grading_policy)
|
||||
self._validate_grading_policy_hash(
|
||||
course_block.location,
|
||||
original_grading_policy_hash
|
||||
)
|
||||
|
||||
|
||||
class MultiProblemModulestoreAccessTestCase(CourseStructureTestCase, SharedModuleStoreTestCase):
|
||||
"""
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
"""
|
||||
Grades Transformer
|
||||
"""
|
||||
from base64 import b64encode
|
||||
from django.test.client import RequestFactory
|
||||
from functools import reduce as functools_reduce
|
||||
from hashlib import sha1
|
||||
from logging import getLogger
|
||||
import json
|
||||
|
||||
from courseware.model_data import FieldDataCache
|
||||
from courseware.module_render import get_module_for_descriptor
|
||||
@@ -64,6 +67,7 @@ class GradesTransformer(BlockStructureTransformer):
|
||||
filter_by=lambda block_key: block_key.block_type == 'sequential',
|
||||
)
|
||||
cls._collect_explicit_graded(block_structure)
|
||||
cls._collect_grading_policy_hash(block_structure)
|
||||
|
||||
def transform(self, block_structure, usage_context):
|
||||
"""
|
||||
@@ -128,6 +132,35 @@ class GradesTransformer(BlockStructureTransformer):
|
||||
if max_score is None:
|
||||
log.warning("GradesTransformer: max_score is None for {}".format(module.location))
|
||||
|
||||
@classmethod
|
||||
def _collect_grading_policy_hash(cls, block_structure):
|
||||
"""
|
||||
Collect a hash of the course's grading policy, storing it as a
|
||||
`transformer_block_field` associated with the `GradesTransformer`.
|
||||
"""
|
||||
def _hash_grading_policy(policy):
|
||||
"""
|
||||
Creates a hash from the course grading policy.
|
||||
The keys are sorted in order to make the hash
|
||||
agnostic to the ordering of the policy coming in.
|
||||
"""
|
||||
ordered_policy = json.dumps(
|
||||
policy,
|
||||
separators=(',', ':'), # Remove spaces from separators for more compact representation
|
||||
sort_keys=True,
|
||||
)
|
||||
return b64encode(sha1(ordered_policy).digest())
|
||||
|
||||
course_location = block_structure.root_block_usage_key
|
||||
course_block = block_structure.get_xblock(course_location)
|
||||
grading_policy = course_block.grading_policy
|
||||
block_structure.set_transformer_block_field(
|
||||
course_block.location,
|
||||
cls,
|
||||
"grading_policy_hash",
|
||||
_hash_grading_policy(grading_policy)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _iter_scorable_xmodules(block_structure):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user