Commit 26f1237d by Usman Khalid

Added tests for xml parsing & serialization.

TNL-708
parent 6c1be448
<openassessment> <openassessment>
<title>Open Assessment Test</title> <title>Open Assessment Test</title>
<prompt> <prompts>
Given the state of the world today, what do you think should be done to <prompt>
combat poverty? Please answer in a short essay of 200-300 words. <description>Given the state of the world today, what do you think should be done to combat poverty? Please answer in a short essay of 200-300 words.</description>
</prompt> </prompt>
</prompts>
<rubric> <rubric>
<prompt>Read for conciseness, clarity of thought, and form.</prompt>
<criterion> <criterion>
<name>Concise</name> <name>Concise</name>
<prompt>How concise is it?</prompt> <prompt>How concise is it?</prompt>
......
{
"promptless": {
"xml": [
"<openassessment>",
"<rubric>",
"</rubric>",
"</openassessment>"
],
"prompts": [{"description": ""}]
},
"rubric_prompt": {
"xml": [
"<openassessment>",
"<rubric>",
"<prompt>Test prompt</prompt>",
"</rubric>",
"</openassessment>"
],
"prompts": [{"description": "Test prompt"}]
},
"rubric_prompt_empty": {
"xml": [
"<openassessment>",
"<rubric>",
"<prompt></prompt>",
"</rubric>",
"</openassessment>"
],
"prompts": [{"description": ""}]
},
"rubric_prompt_unicode": {
"xml": [
"<openassessment>",
"<prompts>",
"<prompt><description>ՇєรՇ קг๏๓קՇ</description></prompt>",
"</prompts>",
"<rubric>",
"<prompt>Test prompt</prompt>",
"</rubric>",
"</openassessment>"
],
"prompts": [{"description": "ՇєรՇ קг๏๓קՇ"}]
},
"prompts_one": {
"xml": [
"<openassessment>",
"<prompts>",
"<prompt><description>Test prompt</description></prompt>",
"</prompts>",
"<rubric>",
"</rubric>",
"</openassessment>"
],
"prompts": [{"description": "Test prompt"}]
},
"prompts_multiple": {
"xml": [
"<openassessment>",
"<prompts>",
"<prompt><description>Test prompt 1</description></prompt>",
"<prompt><description>Test prompt 2</description></prompt>",
"<prompt><description>Test prompt 3</description></prompt>",
"</prompts>",
"<rubric>",
"</rubric>",
"</openassessment>"
],
"prompts": [{"description": "Test prompt 1"}, {"description": "Test prompt 2"}, {"description": "Test prompt 3"}]
},
"prompts_empty": {
"xml": [
"<openassessment>",
"<prompts>",
"<prompt><description></description></prompt>",
"</prompts>",
"<rubric>",
"</rubric>",
"</openassessment>"
],
"prompts": [{"description": ""}]
},
"prompts_multiple_empty": {
"xml": [
"<openassessment>",
"<prompts>",
"<prompt><description></description></prompt>",
"<prompt><description></description></prompt>",
"</prompts>",
"<rubric>",
"<prompt>Test prompt</prompt>",
"</rubric>",
"</openassessment>"
],
"prompts": [{"description": ""}, {"description": ""}]
},
"prompts_unicode": {
"xml": [
"<openassessment>",
"<prompts>",
"<prompt><description>ՇєรՇ קг๏๓קՇ 1</description></prompt>",
"<prompt><description>ՇєรՇ קг๏๓קՇ 2</description></prompt>",
"</prompts>",
"<rubric>",
"</rubric>",
"</openassessment>"
],
"prompts": [{"description": "ՇєรՇ קг๏๓קՇ 1"}, {"description": "ՇєรՇ קг๏๓קՇ 2"}]
},
"rubric_prompt_and_prompts": {
"xml": [
"<openassessment>",
"<prompts>",
"<prompt><description>Test prompt 1</description></prompt>",
"<prompt><description>Test prompt 2</description></prompt>",
"</prompts>",
"<rubric>",
"<prompt>Test prompt</prompt>",
"</rubric>",
"</openassessment>"
],
"prompts": [{"description": "Test prompt 1"}, {"description": "Test prompt 2"}]
}
}
...@@ -211,6 +211,77 @@ ...@@ -211,6 +211,77 @@
] ]
}, },
"multiple_prompts": {
"title": "Foo",
"prompt": "[{\"description\": \"Test prompt 1.\"}, {\"description\": \"Test prompt 2.\"}]",
"rubric_feedback_prompt": "Test Feedback Prompt",
"rubric_feedback_default_text": "Test default text...",
"start": null,
"due": null,
"submission_start": null,
"submission_due": null,
"allow_file_upload": null,
"criteria": [
{
"order_num": 0,
"name": "Test criterion",
"prompt": "Test criterion prompt",
"options": [
{
"order_num": 0,
"points": 0,
"name": "No",
"explanation": "No explanation"
},
{
"order_num": 1,
"points": 2,
"name": "Yes",
"explanation": "Yes explanation"
}
]
}
],
"assessments": [
{
"name": "peer-assessment",
"start": "2014-02-27T09:46:28",
"due": "2014-03-01T00:00:00",
"must_grade": 5,
"must_be_graded_by": 3
},
{
"name": "self-assessment",
"start": "2014-04-01T00:00:00",
"due": "2014-06-01T00:00:00"
}
],
"expected_xml": [
"<openassessment>",
"<title>Foo</title>",
"<assessments>",
"<assessment name=\"peer-assessment\" start=\"2014-02-27T09:46:28\" due=\"2014-03-01T00:00:00\" must_grade=\"5\" must_be_graded_by=\"3\" />",
"<assessment name=\"self-assessment\" start=\"2014-04-01T00:00:00\" due=\"2014-06-01T00:00:00\" />",
"</assessments>",
"<prompts>",
"<prompt><description>Test prompt 1.</description></prompt>",
"<prompt><description>Test prompt 2.</description></prompt>",
"</prompts>",
"<rubric>",
"<criterion>",
"<name>Test criterion</name>",
"<label>Test criterion</label>",
"<prompt>Test criterion prompt</prompt>",
"<option points=\"0\"><name>No</name><label>No</label><explanation>No explanation</explanation></option>",
"<option points=\"2\"><name>Yes</name><label>Yes</label><explanation>Yes explanation</explanation></option>",
"</criterion>",
"<feedbackprompt>Test Feedback Prompt</feedbackprompt>",
"<feedback_default_text>Test default text...</feedback_default_text>",
"</rubric>",
"</openassessment>"
]
},
"unicode": { "unicode": {
"title": "ƒσσ", "title": "ƒσσ",
"prompt": "Ṫëṡẗ ṗṛöṁṗẗ", "prompt": "Ṫëṡẗ ṗṛöṁṗẗ",
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
"</openassessment>" "</openassessment>"
], ],
"title": "Foo", "title": "Foo",
"prompt": "Test prompt", "prompts": [{"description": "Test prompt"}],
"submission_start": null, "submission_start": null,
"submission_due": null, "submission_due": null,
"leaderboard_show": 0, "leaderboard_show": 0,
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
"</rubric>", "</rubric>",
"</openassessment>" "</openassessment>"
], ],
"prompt": null "prompts": [{"description": ""}]
}, },
"empty_prompt": { "empty_prompt": {
...@@ -103,7 +103,7 @@ ...@@ -103,7 +103,7 @@
"</rubric>", "</rubric>",
"</openassessment>" "</openassessment>"
], ],
"prompt": "" "prompt": [{"description": ""}]
}, },
"unicode": { "unicode": {
...@@ -113,8 +113,10 @@ ...@@ -113,8 +113,10 @@
"<assessments>", "<assessments>",
"<assessment name=\"peer-assessment\" start=\"2014-02-27T09:46:28\" due=\"2014-03-01T00:00:00\" must_grade=\"5\" must_be_graded_by=\"3\" />", "<assessment name=\"peer-assessment\" start=\"2014-02-27T09:46:28\" due=\"2014-03-01T00:00:00\" must_grade=\"5\" must_be_graded_by=\"3\" />",
"</assessments>", "</assessments>",
"<prompts>",
"<prompt><description>ՇєรՇ קг๏๓קՇ</description></prompt>",
"</prompts>",
"<rubric>", "<rubric>",
"<prompt>ՇєรՇ קг๏๓קՇ</prompt>",
"<criterion>", "<criterion>",
"<name>𝓣𝓮𝓼𝓽 𝓬𝓻𝓲𝓽𝓮𝓻𝓲𝓸𝓷</name>", "<name>𝓣𝓮𝓼𝓽 𝓬𝓻𝓲𝓽𝓮𝓻𝓲𝓸𝓷</name>",
"<label>Ṫëṡẗ ċṛïẗëṛïöṅ ḷäḅëḷ</label>", "<label>Ṫëṡẗ ċṛïẗëṛïöṅ ḷäḅëḷ</label>",
...@@ -126,7 +128,7 @@ ...@@ -126,7 +128,7 @@
"</openassessment>" "</openassessment>"
], ],
"title": "िѻѻ", "title": "िѻѻ",
"prompt": "ՇєรՇ קг๏๓קՇ", "prompts": [{"description": "ՇєรՇ קг๏๓קՇ"}],
"rubric_criteria": [ "rubric_criteria": [
{ {
"order_num": 0, "order_num": 0,
...@@ -238,7 +240,7 @@ ...@@ -238,7 +240,7 @@
"</rubric>", "</rubric>",
"</openassessment>" "</openassessment>"
], ],
"prompt": "Test prompt", "prompts": [{"description": "Test prompt"}],
"submission_start": null, "submission_start": null,
"submission_due": null "submission_due": null
}, },
......
...@@ -69,6 +69,28 @@ ...@@ -69,6 +69,28 @@
] ]
}, },
"missing_prompt_description": {
"xml": [
"<openassessment>",
"<title>Foo</title>",
"<assessments>",
"<assessment name=\"peer-assessment\" start=\"2014-02-27T09:46:28\" due=\"2014-03-01T00:00:00\" must_grade=\"5\" must_be_graded_by=\"3\" />",
"</assessments>",
"<prompts>",
"<prompt></prompt>",
"</prompts>",
"<rubric>",
"<prompt>Test prompt</prompt>",
"<criterion>",
"<name>Test criterion</name>",
"<prompt>Test criterion prompt</prompt>",
"<option points=\"2\"><name>Yes</name><explanation>Yes explanation</explanation></option>",
"</criterion>",
"</rubric>",
"</openassessment>"
]
},
"non_numeric_points": { "non_numeric_points": {
"xml": [ "xml": [
"<openassessment>", "<openassessment>",
......
...@@ -173,7 +173,12 @@ class TestOpenAssessment(XBlockHandlerTestCase): ...@@ -173,7 +173,12 @@ class TestOpenAssessment(XBlockHandlerTestCase):
@scenario('data/basic_scenario.xml', user_id='Bob') @scenario('data/basic_scenario.xml', user_id='Bob')
def test_prompts_fields(self, xblock): def test_prompts_fields(self, xblock):
self.assertEqual(xblock.prompts, [{'description':'Read for conciseness, clarity of thought, and form.'}]) self.assertEqual(xblock.prompts, [
{
'description': (u'Given the state of the world today, what do you think should be done to '
u'combat poverty? Please answer in a short essay of 200-300 words.')
}
])
xblock.prompt = None xblock.prompt = None
self.assertEqual(xblock.prompts, [{'description': ''}]) self.assertEqual(xblock.prompts, [{'description': ''}])
......
...@@ -14,7 +14,7 @@ import ddt ...@@ -14,7 +14,7 @@ import ddt
from openassessment.xblock.data_conversion import create_prompts_list from openassessment.xblock.data_conversion import create_prompts_list
from openassessment.xblock.openassessmentblock import OpenAssessmentBlock from openassessment.xblock.openassessmentblock import OpenAssessmentBlock
from openassessment.xblock.xml import ( from openassessment.xblock.xml import (
serialize_content, parse_from_xml_str, parse_rubric_xml, serialize_content, parse_from_xml_str, _parse_prompts_xml, parse_rubric_xml,
parse_examples_xml, parse_assessments_xml, parse_examples_xml, parse_assessments_xml,
serialize_rubric_to_xml_str, serialize_examples_to_xml_str, serialize_rubric_to_xml_str, serialize_examples_to_xml_str,
serialize_assessments_to_xml_str, UpdateFromXmlError serialize_assessments_to_xml_str, UpdateFromXmlError
...@@ -61,6 +61,17 @@ class TestSerializeContent(TestCase): ...@@ -61,6 +61,17 @@ class TestSerializeContent(TestCase):
} }
] ]
BASIC_PROMPTS = [
[
{
"description": "Prompt 1."
},
{
"description": "Prompt 2."
}
]
]
BASIC_ASSESSMENTS = [ BASIC_ASSESSMENTS = [
{ {
"name": "student-training", "name": "student-training",
...@@ -200,6 +211,20 @@ class TestSerializeContent(TestCase): ...@@ -200,6 +211,20 @@ class TestSerializeContent(TestCase):
msg = "Could not parse mutated criteria dict {criteria}\n{ex}".format(criteria=mutated_dict, ex=ex) msg = "Could not parse mutated criteria dict {criteria}\n{ex}".format(criteria=mutated_dict, ex=ex)
self.fail(msg) self.fail(msg)
def test_mutated_prompts_dict(self):
self._configure_xblock({})
for prompts_list in self.BASIC_PROMPTS:
for mutated_list in self._list_mutations(prompts_list):
self.oa_block.prompts = mutated_list
xml = serialize_content(self.oa_block)
try:
etree.fromstring(xml)
except Exception as ex: # pylint:disable=W0703
msg = "Could not parse mutated prompts list {prompts}\n{ex}".format(prompts=mutated_list, ex=ex)
self.fail(msg)
def test_mutated_assessments_dict(self): def test_mutated_assessments_dict(self):
self._configure_xblock({}) self._configure_xblock({})
...@@ -320,6 +345,33 @@ class TestSerializeContent(TestCase): ...@@ -320,6 +345,33 @@ class TestSerializeContent(TestCase):
for mutated in self._value_mutations(input_dict, key): for mutated in self._value_mutations(input_dict, key):
yield mutated yield mutated
def _list_mutations(self, input_list):
"""
Iterator over mutations of a list:
1) Empty list
2) Replace list with None
3) Replace list with unicode
4) Replace list with an integer
Args:
input_list (list): A JSON-serializable list to traverse.
Yields:
list
"""
print "== Emptying list"
yield list()
# Mutation #3-5: value mutations
for mutated in (None, u"\u9731", 0):
yield mutated
# Recursively mutate sub-items
for index, item in enumerate(input_list):
if isinstance(item, dict):
for sub_mutation in self._dict_mutations(item):
yield self._mutate_list(input_list, index, sub_mutation)
def _value_mutations(self, input_dict, key): def _value_mutations(self, input_dict, key):
""" """
Iterate over mutations of the value for `key` in a dictionary. Iterate over mutations of the value for `key` in a dictionary.
...@@ -356,6 +408,34 @@ class TestSerializeContent(TestCase): ...@@ -356,6 +408,34 @@ class TestSerializeContent(TestCase):
mutated[key] = new_val mutated[key] = new_val
return mutated return mutated
def _mutate_list(self, input_list, index, new_val):
"""
Copy and update a list.
Args:
input_list (list): The list to copy and update.
index (int): The index of the value to update.
new_val: The new value to set at the index.
Returns:
A copy of the list with the value at `index` set to `new_val`.
"""
mutated = copy.deepcopy(input_list)
mutated[index] = new_val
return mutated
@ddt.ddt
class TestParsePromptsFromXml(TestCase):
@ddt.file_data("data/parse_prompts_xml.json")
def test_parse_prompts_from_xml(self, data):
xml = etree.fromstring("".join(data['xml']))
prompts = _parse_prompts_xml(xml)
self.assertEqual(prompts, data['prompts'])
@ddt.ddt @ddt.ddt
class TestParseRubricFromXml(TestCase): class TestParseRubricFromXml(TestCase):
......
...@@ -67,6 +67,9 @@ def _serialize_prompts(prompts_root, prompts_list): ...@@ -67,6 +67,9 @@ def _serialize_prompts(prompts_root, prompts_list):
Returns: Returns:
None None
""" """
if not isinstance(prompts_list, list):
return
for prompt in prompts_list: for prompt in prompts_list:
prompt_el = etree.SubElement(prompts_root, 'prompt') prompt_el = etree.SubElement(prompts_root, 'prompt')
......
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