Commit ebbbbe6d by Xavier Antoviaque

student-results-migration: Migrate data stored in the `student_results` field

Format change broke backward-compatibility with the previous data format.
Changed `completed` to `status` in `self.student_results` to accomodate
partial responses.
parent eb5de98f
...@@ -39,7 +39,6 @@ from xblock.fragment import Fragment ...@@ -39,7 +39,6 @@ from xblock.fragment import Fragment
from .light_children import XBlockWithLightChildren from .light_children import XBlockWithLightChildren
from .title import TitleBlock from .title import TitleBlock
from .header import SharedHeaderBlock from .header import SharedHeaderBlock
from .html import HTMLBlock
from .message import MentoringMessageBlock from .message import MentoringMessageBlock
from .step import StepParentMixin from .step import StepParentMixin
from .utils import loader from .utils import loader
...@@ -142,6 +141,9 @@ class MentoringBlock(XBlockWithLightChildren, StepParentMixin): ...@@ -142,6 +141,9 @@ class MentoringBlock(XBlockWithLightChildren, StepParentMixin):
return Score(score, int(round(score * 100)), correct, incorrect, partially_correct) return Score(score, int(round(score * 100)), correct, incorrect, partially_correct)
def student_view(self, context): def student_view(self, context):
# Migrate stored data if necessary
self.migrate_fields()
fragment, named_children = self.get_children_fragment( fragment, named_children = self.get_children_fragment(
context, view_name='mentoring_view', context, view_name='mentoring_view',
not_instance_of=self.FLOATING_BLOCKS, not_instance_of=self.FLOATING_BLOCKS,
...@@ -172,6 +174,18 @@ class MentoringBlock(XBlockWithLightChildren, StepParentMixin): ...@@ -172,6 +174,18 @@ class MentoringBlock(XBlockWithLightChildren, StepParentMixin):
return fragment return fragment
def migrate_fields(self):
"""
Migrate data stored in the fields, when a format change breaks backward-compatibility with
previous data formats
"""
# Partial answers replaced the `completed` with `status` in `self.student_results`
if self.student_results and 'completed' in self.student_results[0][1]:
# Rename the field and use the new value format (text instead of boolean)
for result in self.student_results:
result[1]['status'] = 'correct' if result[1]['completed'] else 'incorrect'
del result[1]['completed']
@property @property
def additional_publish_event_data(self): def additional_publish_event_data(self):
return { return {
......
import copy
import unittest import unittest
from mock import MagicMock, Mock
from lxml import etree from xblock.field_data import DictFieldData
from mentoring import MentoringBlock from mentoring import MentoringBlock
import mentoring
from mentoring.step import StepMixin, StepParentMixin from mentoring.step import StepMixin, StepParentMixin
...@@ -78,3 +79,37 @@ class TestStepMixin(unittest.TestCase): ...@@ -78,3 +79,37 @@ class TestStepMixin(unittest.TestCase):
self.assertFalse(step1.lonely_step) self.assertFalse(step1.lonely_step)
self.assertFalse(step2.lonely_step) self.assertFalse(step2.lonely_step)
class TestFieldMigration(unittest.TestCase):
"""
Test mentoring fields data migration
"""
def test_partial_completion_status_migration(self):
"""
Changed `completed` to `status` in `self.student_results` to accomodate partial responses
"""
# Instantiate a mentoring block with the old format
student_results = [
[ u'goal',
{ u'completed': True,
u'score': 1,
u'student_input': u'test',
u'weight': 1}],
[ u'mcq_1_1',
{ u'completed': False,
u'score': 0,
u'submission': u'maybenot',
u'weight': 1}],
]
mentoring = MentoringBlock(MagicMock(), DictFieldData({'student_results': student_results}), Mock())
self.assertEqual(copy.deepcopy(student_results), mentoring.student_results)
migrated_student_results = copy.deepcopy(student_results)
migrated_student_results[0][1]['status'] = 'correct'
migrated_student_results[1][1]['status'] = 'incorrect'
del migrated_student_results[0][1]['completed']
del migrated_student_results[1][1]['completed']
mentoring.migrate_fields()
self.assertEqual(migrated_student_results, mentoring.student_results)
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