Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-ora2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-ora2
Commits
a83b25cf
Commit
a83b25cf
authored
Jun 05, 2014
by
Stephen Sanchez
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Split XML serialization and validation contracts.
parent
041e5e43
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
606 additions
and
234 deletions
+606
-234
openassessment/xblock/openassessmentblock.py
+53
-2
openassessment/xblock/studio_mixin.py
+66
-27
openassessment/xblock/test/data/invalid_assessment.xml
+0
-17
openassessment/xblock/test/data/invalid_dates.xml
+0
-91
openassessment/xblock/test/data/invalid_rubric.json
+29
-0
openassessment/xblock/test/data/invalid_rubric.xml
+0
-15
openassessment/xblock/test/data/invalid_update_xblock.json
+84
-0
openassessment/xblock/test/data/parse_assessments_xml.json
+159
-0
openassessment/xblock/test/data/parse_examples_xml.json
+64
-0
openassessment/xblock/test/data/parse_rubric_xml.json
+0
-0
openassessment/xblock/test/data/update_xblock.json
+30
-0
openassessment/xblock/test/test_studio.py
+54
-53
openassessment/xblock/test/test_xml.py
+67
-29
openassessment/xblock/xml.py
+0
-0
No files found.
openassessment/xblock/openassessmentblock.py
View file @
a83b25cf
...
@@ -22,7 +22,7 @@ from openassessment.xblock.lms_mixin import LmsCompatibilityMixin
...
@@ -22,7 +22,7 @@ from openassessment.xblock.lms_mixin import LmsCompatibilityMixin
from
openassessment.xblock.self_assessment_mixin
import
SelfAssessmentMixin
from
openassessment.xblock.self_assessment_mixin
import
SelfAssessmentMixin
from
openassessment.xblock.submission_mixin
import
SubmissionMixin
from
openassessment.xblock.submission_mixin
import
SubmissionMixin
from
openassessment.xblock.studio_mixin
import
StudioMixin
from
openassessment.xblock.studio_mixin
import
StudioMixin
from
openassessment.xblock.xml
import
updat
e_from_xml
,
serialize_content_to_xml
from
openassessment.xblock.xml
import
pars
e_from_xml
,
serialize_content_to_xml
from
openassessment.xblock.staff_info_mixin
import
StaffInfoMixin
from
openassessment.xblock.staff_info_mixin
import
StaffInfoMixin
from
openassessment.xblock.workflow_mixin
import
WorkflowMixin
from
openassessment.xblock.workflow_mixin
import
WorkflowMixin
from
openassessment.workflow
import
api
as
workflow_api
from
openassessment.workflow
import
api
as
workflow_api
...
@@ -324,8 +324,59 @@ class OpenAssessmentBlock(
...
@@ -324,8 +324,59 @@ class OpenAssessmentBlock(
"""
"""
block
=
runtime
.
construct_xblock_from_class
(
cls
,
keys
)
block
=
runtime
.
construct_xblock_from_class
(
cls
,
keys
)
config
=
parse_from_xml
(
node
)
rubric
=
{
"prompt"
:
config
[
"prompt"
],
"feedbackprompt"
:
config
[
"rubric_feedback_prompt"
],
"criteria"
:
config
[
"rubric_criteria"
],
}
xblock_validator
=
validator
(
block
,
strict_post_release
=
False
)
xblock_validator
(
rubric
,
{
'due'
:
config
[
'submission_due'
]},
config
[
'rubric_assessments'
]
)
block
.
update
(
config
[
'rubric_criteria'
],
config
[
'rubric_feedback_prompt'
],
config
[
'rubric_assessments'
],
config
[
'submission_due'
],
config
[
'submission_start'
],
config
[
'title'
],
config
[
'prompt'
]
)
return
block
def
update
(
self
,
criteria
,
feedback_prompt
,
assessments
,
submission_due
,
submission_start
,
title
,
prompt
):
"""
Given a dictionary of properties, update the XBlock
Args:
criteria (list): A list of rubric criteria for this XBlock.
feedback_prompt (str):
assessments (list): A list of assessment module configurations for
this XBlock.
submission_due (str): ISO formatted submission due date.
submission_start (str): ISO formatted submission start date.
title (str): The title of this XBlock
prompt (str): The prompt for this XBlock.
return
update_from_xml
(
block
,
node
,
validator
=
validator
(
block
,
strict_post_release
=
False
))
Returns:
None
"""
# If we've gotten this far, then we've successfully parsed the XML
# and validated the contents. At long last, we can safely update the XBlock.
self
.
title
=
title
self
.
prompt
=
prompt
self
.
rubric_criteria
=
criteria
self
.
rubric_assessments
=
assessments
self
.
rubric_feedback_prompt
=
feedback_prompt
self
.
submission_start
=
submission_start
self
.
submission_due
=
submission_due
@property
@property
def
valid_assessments
(
self
):
def
valid_assessments
(
self
):
...
...
openassessment/xblock/studio_mixin.py
View file @
a83b25cf
...
@@ -8,7 +8,7 @@ from django.template.loader import get_template
...
@@ -8,7 +8,7 @@ from django.template.loader import get_template
from
django.utils.translation
import
ugettext
as
_
from
django.utils.translation
import
ugettext
as
_
from
xblock.core
import
XBlock
from
xblock.core
import
XBlock
from
xblock.fragment
import
Fragment
from
xblock.fragment
import
Fragment
from
openassessment.xblock
.xml
import
serialize_content
,
update_from_xml_str
,
ValidationError
,
UpdateFromXmlError
from
openassessment.xblock
import
xml
from
openassessment.xblock.validation
import
validator
from
openassessment.xblock.validation
import
validator
...
@@ -37,13 +37,17 @@ class StudioMixin(object):
...
@@ -37,13 +37,17 @@ class StudioMixin(object):
return
frag
return
frag
@XBlock.json_handler
@XBlock.json_handler
def
update_
xml
(
self
,
data
,
suffix
=
''
):
def
update_
editor_context
(
self
,
data
,
suffix
=
''
):
"""
"""
Update the XBlock's
XML
.
Update the XBlock's
configuration
.
Args:
Args:
data (dict): Data from the request; should have a value for the key 'xml'
data (dict): Data from the request; should have a value for the keys
containing the XML for this XBlock.
'rubric', 'settings' and 'prompt'. The 'rubric' should be an XML
representation of the new rubric. The 'prompt' should be a plain
text prompt. The 'settings' should be a dict of 'title',
'submission_due', 'submission_start' and the XML configuration for
all 'assessments'.
Kwargs:
Kwargs:
suffix (str): Not used
suffix (str): Not used
...
@@ -51,26 +55,43 @@ class StudioMixin(object):
...
@@ -51,26 +55,43 @@ class StudioMixin(object):
Returns:
Returns:
dict with keys 'success' (bool) and 'msg' (str)
dict with keys 'success' (bool) and 'msg' (str)
"""
"""
if
'xml'
in
data
:
missing_keys
=
list
({
'rubric'
,
'settings'
,
'prompt'
}
-
set
(
data
.
keys
()))
try
:
if
missing_keys
:
update_from_xml_str
(
self
,
data
[
'xml'
],
validator
=
validator
(
self
))
logger
.
warn
(
'Must specify the following keys in request JSON dict: {}'
.
format
(
missing_keys
)
except
ValidationError
as
ex
:
)
return
{
'success'
:
False
,
'msg'
:
_
(
'Validation error: {error}'
)
.
format
(
error
=
ex
)}
return
{
'success'
:
False
,
'msg'
:
_
(
'Error updating XBlock configuration'
)}
settings
=
data
[
'settings'
]
except
UpdateFromXmlError
as
ex
:
try
:
return
{
'success'
:
False
,
'msg'
:
_
(
'An error occurred while saving: {error}'
)
.
format
(
error
=
ex
)}
else
:
return
{
'success'
:
True
,
'msg'
:
_
(
'Successfully updated OpenAssessment XBlock'
)}
else
:
rubric
=
xml
.
parse_rubric_xml_str
(
data
[
'rubric'
])
return
{
'success'
:
False
,
'msg'
:
_
(
'Must specify "xml" in request JSON dict.'
)}
assessments
=
xml
.
parse_assessments_xml_str
(
settings
[
'assessments'
])
submission_due
=
settings
[
"submission_due"
]
except
xml
.
UpdateFromXmlError
as
ex
:
return
{
'success'
:
False
,
'msg'
:
_
(
'An error occurred while saving: {error}'
)
.
format
(
error
=
ex
)}
xblock_validator
=
validator
(
self
)
success
,
msg
=
xblock_validator
(
rubric
,
{
'due'
:
submission_due
},
assessments
)
if
not
success
:
return
{
'success'
:
False
,
'msg'
:
_
(
'Validation error: {error}'
)
.
format
(
error
=
msg
)}
self
.
update
(
rubric
[
'criteria'
],
rubric
[
'feedbackprompt'
],
assessments
,
settings
[
"submission_due"
],
settings
[
"submission_start"
],
settings
[
"title"
],
data
[
"prompt"
]
)
return
{
'success'
:
True
,
'msg'
:
'Successfully updated OpenAssessment XBlock'
}
@XBlock.json_handler
@XBlock.json_handler
def
xml
(
self
,
data
,
suffix
=
''
):
def
editor_context
(
self
,
data
,
suffix
=
''
):
"""
"""
Retrieve the XBlock's content definition, serialized as XML.
Retrieve the XBlock's content definition, serialized as a JSON object
containing all the configuration as it will be displayed for studio
editing.
Args:
Args:
data (dict): Not used
data (dict): Not used
...
@@ -79,19 +100,37 @@ class StudioMixin(object):
...
@@ -79,19 +100,37 @@ class StudioMixin(object):
suffix (str): Not used
suffix (str): Not used
Returns:
Returns:
dict with keys 'success' (bool), 'message' (unicode), and 'xml' (unicode)
dict with keys 'success' (bool), 'message' (unicode),
'rubric' (unicode), 'prompt' (unicode), and 'settings' (dict)
"""
"""
try
:
try
:
xml
=
serialize_content
(
self
)
assessments
=
xml
.
serialize_assessments_to_xml_str
(
self
)
rubric
=
xml
.
serialize_rubric_to_xml_str
(
self
)
# We do not expect
`serialize_content`
to raise an exception,
# We do not expect
serialization
to raise an exception,
# but if it does, handle it gracefully.
# but if it does, handle it gracefully.
except
Exception
as
ex
:
except
Exception
as
ex
:
msg
=
_
(
'An unexpected error occurred while loading the problem: {error}'
)
.
format
(
error
=
ex
)
msg
=
_
(
'An unexpected error occurred while loading the problem: {error}'
)
.
format
(
error
=
ex
)
logger
.
error
(
msg
)
logger
.
error
(
msg
)
return
{
'success'
:
False
,
'msg'
:
msg
,
'xml'
:
u''
}
return
{
'success'
:
False
,
'msg'
:
msg
,
'xml'
:
u''
}
else
:
return
{
'success'
:
True
,
'msg'
:
''
,
'xml'
:
xml
}
# Populates the context for the assessments section of the editing
# panel. This will adjust according to the fields laid out in this
# section.
settings
=
{
'submission_due'
:
self
.
submission_due
,
'submission_start'
:
self
.
submission_start
,
'title'
:
self
.
title
,
'assessments'
:
assessments
}
return
{
'success'
:
True
,
'msg'
:
''
,
'rubric'
:
rubric
,
'prompt'
:
self
.
prompt
,
'settings'
:
settings
}
@XBlock.json_handler
@XBlock.json_handler
def
check_released
(
self
,
data
,
suffix
=
''
):
def
check_released
(
self
,
data
,
suffix
=
''
):
...
...
openassessment/xblock/test/data/invalid_assessment.xml
deleted
100644 → 0
View file @
041e5e43
<openassessment>
<title>
Foo
</title>
<assessments>
<!-- assessment name not supported -->
<assessment
name=
"unsupported-assessment"
/>
<assessment
name=
"self-assessment"
/>
</assessments>
<rubric>
<prompt>
Test prompt
</prompt>
<criterion>
<name>
Test criterion
</name>
<prompt>
Test criterion prompt
</prompt>
<option
points=
"0"
><name>
No
</name><explanation>
No explanation
</explanation></option>
<option
points=
"2"
><name>
Yes
</name><explanation>
Yes explanation
</explanation></option>
</criterion>
</rubric>
</openassessment>
openassessment/xblock/test/data/invalid_dates.xml
deleted
100644 → 0
View file @
041e5e43
<openassessment>
<title>
Open Assessment Test
</title>
<prompt>
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.
</prompt>
<rubric>
<prompt>
Read for conciseness, clarity of thought, and form.
</prompt>
<criterion>
<name>
Concise
</name>
<prompt>
How concise is it?
</prompt>
<option
points=
"0"
>
<name>
Neal Stephenson (late)
</name>
<explanation>
Neal Stephenson explanation
</explanation>
</option>
<option
points=
"1"
>
<name>
HP Lovecraft
</name>
<explanation>
HP Lovecraft explanation
</explanation>
</option>
<option
points=
"3"
>
<name>
Robert Heinlein
</name>
<explanation>
Robert Heinlein explanation
</explanation>
</option>
<option
points=
"4"
>
<name>
Neal Stephenson (early)
</name>
<explanation>
Neal Stephenson (early) explanation
</explanation>
</option>
<option
points=
"5"
>
<name>
Earnest Hemingway
</name>
<explanation>
Earnest Hemingway
</explanation>
</option>
</criterion>
<criterion>
<name>
Clear-headed
</name>
<prompt>
How clear is the thinking?
</prompt>
<option
points=
"0"
>
<name>
Yogi Berra
</name>
<explanation>
Yogi Berra explanation
</explanation>
</option>
<option
points=
"1"
>
<name>
Hunter S. Thompson
</name>
<explanation>
Hunter S. Thompson explanation
</explanation>
</option>
<option
points=
"2"
>
<name>
Robert Heinlein
</name>
<explanation>
Robert Heinlein explanation
</explanation>
</option>
<option
points=
"3"
>
<name>
Isaac Asimov
</name>
<explanation>
Isaac Asimov explanation
</explanation>
</option>
<option
points=
"10"
>
<name>
Spock
</name>
<explanation>
Spock explanation
</explanation>
</option>
</criterion>
<criterion>
<name>
Form
</name>
<prompt>
Lastly, how is its form? Punctuation, grammar, and spelling all count.
</prompt>
<option
points=
"0"
>
<name>
lolcats
</name>
<explanation>
lolcats explanation
</explanation>
</option>
<option
points=
"1"
>
<name>
Facebook
</name>
<explanation>
Facebook explanation
</explanation>
</option>
<option
points=
"2"
>
<name>
Reddit
</name>
<explanation>
Reddit explanation
</explanation>
</option>
<option
points=
"3"
>
<name>
metafilter
</name>
<explanation>
metafilter explanation
</explanation>
</option>
<option
points=
"4"
>
<name>
Usenet, 1996
</name>
<explanation>
Usenet, 1996 explanation
</explanation>
</option>
<option
points=
"5"
>
<name>
The Elements of Style
</name>
<explanation>
The Elements of Style explanation
</explanation>
</option>
</criterion>
</rubric>
<assessments>
<!-- start date is after due date -->
<assessment
name=
"peer-assessment"
must_grade=
"5"
must_be_graded_by=
"3"
/>
<assessment
name=
"self-assessment"
start=
"2010-01-01"
due=
"2003-01-01"
/>
</assessments>
</openassessment>
openassessment/xblock/test/data/invalid_rubric.json
0 → 100644
View file @
a83b25cf
{
"simple"
:
{
"rubric"
:
[
"<rubric>"
,
"<prompt>Test prompt</prompt>"
,
"<criterion>"
,
"<name>Test criterion</name>"
,
"<prompt>Test criterion prompt</prompt>"
,
"<!-- no options -->"
,
"</criterion>"
,
"</rubric>"
],
"prompt"
:
"My new prompt."
,
"settings"
:
{
"title"
:
"My new title."
,
"assessments"
:
[
"<assessments>"
,
"<assessment name=
\"
peer-assessment
\"
must_grade=
\"
5
\"
must_be_graded_by=
\"
3
\"
/>"
,
"<assessment name=
\"
self-assessment
\"
/>"
,
"</assessments>"
],
"submission_due"
:
"2014-02-27T09:46:28"
,
"submission_start"
:
"2014-02-10T09:46:28"
},
"expected-assessment"
:
"peer-assessment"
,
"expected-criterion-prompt"
:
"Test criterion prompt"
}
}
\ No newline at end of file
openassessment/xblock/test/data/invalid_rubric.xml
deleted
100644 → 0
View file @
041e5e43
<openassessment>
<title>
Foo
</title>
<assessments>
<assessment
name=
"peer-assessment"
must_grade=
"5"
must_be_graded_by=
"3"
/>
<assessment
name=
"self-assessment"
/>
</assessments>
<rubric>
<prompt>
Test prompt
</prompt>
<criterion>
<name>
Test criterion
</name>
<prompt>
Test criterion prompt
</prompt>
<!-- no options -->
</criterion>
</rubric>
</openassessment>
openassessment/xblock/test/data/invalid_update_xblock.json
0 → 100644
View file @
a83b25cf
{
"no_rubric"
:
{
"prompt"
:
"My new prompt."
,
"settings"
:
{
"title"
:
"My new title."
,
"assessments"
:
[
"<assessments>"
,
"<assessment name=
\"
peer-assessment
\"
must_grade=
\"
5
\"
must_be_graded_by=
\"
3
\"
/>"
,
"<assessment name=
\"
self-assessment
\"
/>"
,
"</assessments>"
],
"submission_due"
:
"2014-02-27T09:46:28"
,
"submission_start"
:
"2014-02-10T09:46:28"
},
"expected_error"
:
"error"
},
"no_prompt"
:
{
"rubric"
:
[
"<rubric>"
,
"<prompt>Test prompt</prompt>"
,
"<criterion>"
,
"<name>Test criterion</name>"
,
"<prompt>Test criterion prompt</prompt>"
,
"<option points=
\"
0
\"
><name>No</name><explanation>No explanation</explanation></option>"
,
"<option points=
\"
2
\"
><name>Yes</name><explanation>Yes explanation</explanation></option>"
,
"</criterion>"
,
"</rubric>"
],
"settings"
:
{
"title"
:
"My new title."
,
"assessments"
:
[
"<assessments>"
,
"<assessment name=
\"
peer-assessment
\"
must_grade=
\"
5
\"
must_be_graded_by=
\"
3
\"
/>"
,
"<assessment name=
\"
self-assessment
\"
/>"
,
"</assessments>"
],
"submission_due"
:
"2014-02-27T09:46:28"
,
"submission_start"
:
"2014-02-10T09:46:28"
},
"expected_error"
:
"error"
},
"no_settings"
:
{
"rubric"
:
[
"<rubric>"
,
"<prompt>Test prompt</prompt>"
,
"<criterion>"
,
"<name>Test criterion</name>"
,
"<prompt>Test criterion prompt</prompt>"
,
"<option points=
\"
0
\"
><name>No</name><explanation>No explanation</explanation></option>"
,
"<option points=
\"
2
\"
><name>Yes</name><explanation>Yes explanation</explanation></option>"
,
"</criterion>"
,
"</rubric>"
],
"prompt"
:
"My new prompt."
,
"expected_error"
:
"error"
},
"invalid_dates"
:
{
"rubric"
:
[
"<rubric>"
,
"<prompt>Test prompt</prompt>"
,
"<criterion>"
,
"<name>Test criterion</name>"
,
"<prompt>Test criterion prompt</prompt>"
,
"<option points=
\"
0
\"
><name>No</name><explanation>No explanation</explanation></option>"
,
"<option points=
\"
2
\"
><name>Yes</name><explanation>Yes explanation</explanation></option>"
,
"</criterion>"
,
"</rubric>"
],
"prompt"
:
"My new prompt."
,
"settings"
:
{
"title"
:
"My new title."
,
"assessments"
:
[
"<assessments>"
,
"<assessment name=
\"
peer-assessment
\"
must_grade=
\"
5
\"
must_be_graded_by=
\"
3
\"
/>"
,
"<assessment name=
\"
self-assessment
\"
start=
\"
2010-01-01
\"
due=
\"
2003-01-01
\"
/>"
,
"</assessments>"
],
"submission_due"
:
"2012-02-27T09:46:28"
,
"submission_start"
:
"2015-02-10T09:46:28"
},
"expected_error"
:
"cannot be later"
}
}
\ No newline at end of file
openassessment/xblock/test/data/parse_assessments_xml.json
0 → 100644
View file @
a83b25cf
{
"simple"
:
{
"xml"
:
[
"<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>"
],
"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"
}
]
},
"multiple_criteria"
:
{
"xml"
:
[
"<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>"
],
"assessments"
:
[
{
"name"
:
"peer-assessment"
,
"start"
:
"2014-02-27T09:46:28"
,
"due"
:
"2014-03-01T00:00:00"
,
"must_grade"
:
5
,
"must_be_graded_by"
:
3
}
]
},
"no_dates_specified"
:
{
"xml"
:
[
"<assessments>"
,
"<assessment name=
\"
peer-assessment
\"
must_grade=
\"
5
\"
must_be_graded_by=
\"
3
\"
/>"
,
"</assessments>"
],
"assessments"
:
[
{
"name"
:
"peer-assessment"
,
"start"
:
null
,
"due"
:
null
,
"must_grade"
:
5
,
"must_be_graded_by"
:
3
}
]
},
"student_training_no_examples"
:
{
"xml"
:
[
"<assessments>"
,
"<assessment name=
\"
student-training
\"
start=
\"
2014-04-01T00:00:00
\"
due=
\"
2014-06-01T00:00:00
\"
/>"
,
"</assessments>"
],
"assessments"
:
[
{
"name"
:
"student-training"
,
"start"
:
"2014-04-01T00:00:00"
,
"due"
:
"2014-06-01T00:00:00"
,
"examples"
:
[]
}
]
},
"student_training_one_example"
:
{
"xml"
:
[
"<assessments>"
,
"<assessment name=
\"
student-training
\"
start=
\"
2014-04-01T00:00:00
\"
due=
\"
2014-06-01T00:00:00
\"
>"
,
"<example>"
,
"<answer>ẗëṡẗ äṅṡẅëṛ</answer>"
,
"<select criterion=
\"
Test criterion
\"
option=
\"
Yes
\"
/>"
,
"</example>"
,
"</assessment>"
,
"</assessments>"
],
"assessments"
:
[
{
"name"
:
"student-training"
,
"start"
:
"2014-04-01T00:00:00"
,
"due"
:
"2014-06-01T00:00:00"
,
"examples"
:
[
{
"answer"
:
"ẗëṡẗ äṅṡẅëṛ"
,
"options_selected"
:
[
{
"criterion"
:
"Test criterion"
,
"option"
:
"Yes"
}
]
}
]
}
]
},
"student_training_multiple_examples"
:
{
"xml"
:
[
"<assessments>"
,
"<assessment name=
\"
student-training
\"
start=
\"
2014-04-01T00:00:00
\"
due=
\"
2014-06-01T00:00:00
\"
>"
,
"<example>"
,
"<answer>ẗëṡẗ äṅṡẅëṛ</answer>"
,
"<select criterion=
\"
Test criterion
\"
option=
\"
Yes
\"
/>"
,
"<select criterion=
\"
Another test criterion
\"
option=
\"
No
\"
/>"
,
"</example>"
,
"<example>"
,
"<answer>äṅöẗḧëṛ ẗëṡẗ äṅṡẅëṛ</answer>"
,
"<select criterion=
\"
Another test criterion
\"
option=
\"
Yes
\"
/>"
,
"<select criterion=
\"
Test criterion
\"
option=
\"
No
\"
/>"
,
"</example>"
,
"</assessment>"
,
"</assessments>"
],
"assessments"
:
[
{
"name"
:
"student-training"
,
"start"
:
"2014-04-01T00:00:00"
,
"due"
:
"2014-06-01T00:00:00"
,
"examples"
:
[
{
"answer"
:
"ẗëṡẗ äṅṡẅëṛ"
,
"options_selected"
:
[
{
"criterion"
:
"Test criterion"
,
"option"
:
"Yes"
},
{
"criterion"
:
"Another test criterion"
,
"option"
:
"No"
}
]
},
{
"answer"
:
"äṅöẗḧëṛ ẗëṡẗ äṅṡẅëṛ"
,
"options_selected"
:
[
{
"criterion"
:
"Another test criterion"
,
"option"
:
"Yes"
},
{
"criterion"
:
"Test criterion"
,
"option"
:
"No"
}
]
}
]
}
]
}
}
openassessment/xblock/test/data/parse_examples_xml.json
0 → 100644
View file @
a83b25cf
{
"student_training_one_example"
:
{
"xml"
:
[
"<example>"
,
"<answer>ẗëṡẗ äṅṡẅëṛ</answer>"
,
"<select criterion=
\"
Test criterion
\"
option=
\"
Yes
\"
/>"
,
"</example>"
],
"examples"
:
[
{
"answer"
:
"ẗëṡẗ äṅṡẅëṛ"
,
"options_selected"
:
[
{
"criterion"
:
"Test criterion"
,
"option"
:
"Yes"
}
]
}
]
},
"student_training_multiple_examples"
:
{
"xml"
:
[
"<example>"
,
"<answer>ẗëṡẗ äṅṡẅëṛ</answer>"
,
"<select criterion=
\"
Test criterion
\"
option=
\"
Yes
\"
/>"
,
"<select criterion=
\"
Another test criterion
\"
option=
\"
No
\"
/>"
,
"</example>"
,
"<example>"
,
"<answer>äṅöẗḧëṛ ẗëṡẗ äṅṡẅëṛ</answer>"
,
"<select criterion=
\"
Another test criterion
\"
option=
\"
Yes
\"
/>"
,
"<select criterion=
\"
Test criterion
\"
option=
\"
No
\"
/>"
,
"</example>"
],
"examples"
:
[
{
"answer"
:
"ẗëṡẗ äṅṡẅëṛ"
,
"options_selected"
:
[
{
"criterion"
:
"Test criterion"
,
"option"
:
"Yes"
},
{
"criterion"
:
"Another test criterion"
,
"option"
:
"No"
}
]
},
{
"answer"
:
"äṅöẗḧëṛ ẗëṡẗ äṅṡẅëṛ"
,
"options_selected"
:
[
{
"criterion"
:
"Another test criterion"
,
"option"
:
"Yes"
},
{
"criterion"
:
"Test criterion"
,
"option"
:
"No"
}
]
}
]
}
}
openassessment/xblock/test/data/parse_rubric_xml.json
0 → 100644
View file @
a83b25cf
This diff is collapsed.
Click to expand it.
openassessment/xblock/test/data/update_xblock.json
0 → 100644
View file @
a83b25cf
{
"simple"
:
{
"rubric"
:
[
"<rubric>"
,
"<prompt>Test prompt</prompt>"
,
"<criterion>"
,
"<name>Test criterion</name>"
,
"<prompt>Test criterion prompt</prompt>"
,
"<option points=
\"
0
\"
><name>No</name><explanation>No explanation</explanation></option>"
,
"<option points=
\"
2
\"
><name>Yes</name><explanation>Yes explanation</explanation></option>"
,
"</criterion>"
,
"</rubric>"
],
"prompt"
:
"My new prompt."
,
"settings"
:
{
"title"
:
"My new title."
,
"assessments"
:
[
"<assessments>"
,
"<assessment name=
\"
peer-assessment
\"
must_grade=
\"
5
\"
must_be_graded_by=
\"
3
\"
/>"
,
"<assessment name=
\"
self-assessment
\"
/>"
,
"</assessments>"
],
"submission_due"
:
"4014-02-27T09:46:28"
,
"submission_start"
:
"4014-02-10T09:46:28"
},
"expected-assessment"
:
"peer-assessment"
,
"expected-criterion-prompt"
:
"Test criterion prompt"
}
}
\ No newline at end of file
openassessment/xblock/test/test_studio.py
View file @
a83b25cf
...
@@ -7,7 +7,8 @@ import datetime as dt
...
@@ -7,7 +7,8 @@ import datetime as dt
import
lxml.etree
as
etree
import
lxml.etree
as
etree
import
mock
import
mock
import
pytz
import
pytz
from
ddt
import
ddt
,
data
from
ddt
import
ddt
,
data
,
file_data
from
openassessment.xblock.xml
import
UpdateFromXmlError
from
.base
import
scenario
,
XBlockHandlerTestCase
from
.base
import
scenario
,
XBlockHandlerTestCase
...
@@ -23,92 +24,92 @@ class StudioViewTest(XBlockHandlerTestCase):
...
@@ -23,92 +24,92 @@ class StudioViewTest(XBlockHandlerTestCase):
self
.
assertTrue
(
frag
.
body_html
()
.
find
(
'openassessment-edit'
))
self
.
assertTrue
(
frag
.
body_html
()
.
find
(
'openassessment-edit'
))
@scenario
(
'data/basic_scenario.xml'
)
@scenario
(
'data/basic_scenario.xml'
)
def
test_get_
xml
(
self
,
xblock
):
def
test_get_
editor_context
(
self
,
xblock
):
resp
=
self
.
request
(
xblock
,
'
xml
'
,
'""'
,
response_format
=
'json'
)
resp
=
self
.
request
(
xblock
,
'
editor_context
'
,
'""'
,
response_format
=
'json'
)
self
.
assertTrue
(
resp
[
'success'
])
self
.
assertTrue
(
resp
[
'success'
])
self
.
assertEqual
(
resp
[
'msg'
],
u''
)
self
.
assertEqual
(
resp
[
'msg'
],
u''
)
# Verify that the
XML is parseable and the root is <openassessment
>
# Verify that the
Rubric XML is parse-able and the root is <rubric
>
r
oot
=
etree
.
fromstring
(
resp
[
'xml
'
])
r
ubric
=
etree
.
fromstring
(
resp
[
'rubric
'
])
self
.
assertEqual
(
r
oot
.
tag
,
'openassessment
'
)
self
.
assertEqual
(
r
ubric
.
tag
,
'rubric
'
)
@mock.patch
(
'openassessment.xblock.studio_mixin.serialize_content'
)
assessments
=
etree
.
fromstring
(
resp
[
'settings'
][
'assessments'
])
self
.
assertEqual
(
assessments
.
tag
,
'assessments'
)
@mock.patch
(
'openassessment.xblock.xml.serialize_rubric_to_xml_str'
)
@scenario
(
'data/basic_scenario.xml'
)
@scenario
(
'data/basic_scenario.xml'
)
def
test_get_
xml_error
(
self
,
xblock
,
mock_serialize
):
def
test_get_
editor_context_error
(
self
,
xblock
,
mock_rubric_serializer
):
# Simulate an unexpected error while serializing the XBlock
# Simulate an unexpected error while serializing the XBlock
mock_
serialize
.
side_effect
=
Value
Error
(
'Test error!'
)
mock_
rubric_serializer
.
side_effect
=
UpdateFromXml
Error
(
'Test error!'
)
# Check that we get a failure message
# Check that we get a failure message
resp
=
self
.
request
(
xblock
,
'
xml
'
,
'""'
,
response_format
=
'json'
)
resp
=
self
.
request
(
xblock
,
'
editor_context
'
,
'""'
,
response_format
=
'json'
)
self
.
assertFalse
(
resp
[
'success'
])
self
.
assertFalse
(
resp
[
'success'
])
self
.
assertIn
(
u'unexpected error'
,
resp
[
'msg'
]
.
lower
())
self
.
assertIn
(
u'unexpected error'
,
resp
[
'msg'
]
.
lower
())
@file_data
(
'data/update_xblock.json'
)
@scenario
(
'data/basic_scenario.xml'
)
@scenario
(
'data/basic_scenario.xml'
)
def
test_update_x
ml
(
self
,
xblock
):
def
test_update_x
block
(
self
,
xblock
,
data
):
# First, parse XML data into a single string.
# Set the XBlock's release date to the future,
data
[
'rubric'
]
=
""
.
join
(
data
[
'rubric'
])
# so we are not restricted in what we can edit
data
[
'settings'
][
'assessments'
]
=
""
.
join
(
data
[
'settings'
][
'assessments'
])
xblock
.
start
=
dt
.
datetime
(
3000
,
1
,
1
)
.
replace
(
tzinfo
=
pytz
.
utc
)
xblock
.
published_date
=
None
# Test that we can update the xblock with the expected configuration.
request
=
json
.
dumps
(
{
'xml'
:
self
.
load_fixture_str
(
'data/updated_block.xml'
)}
)
request
=
json
.
dumps
(
data
)
# Verify the response is successfully
# Verify the response is successfully
resp
=
self
.
request
(
xblock
,
'update_xml'
,
request
,
response_format
=
'json'
)
resp
=
self
.
request
(
xblock
,
'update_editor_context'
,
request
,
response_format
=
'json'
)
print
"ERROR IS {}"
.
format
(
resp
[
'msg'
])
self
.
assertTrue
(
resp
[
'success'
])
self
.
assertTrue
(
resp
[
'success'
])
self
.
assertIn
(
'success'
,
resp
[
'msg'
]
.
lower
())
self
.
assertIn
(
'success'
,
resp
[
'msg'
]
.
lower
())
# Check that the XBlock fields were updated
# Check that the XBlock fields were updated
# We don't need to be exhaustive here, because we have other unit tests
# We don't need to be exhaustive here, because we have other unit tests
# that verify this extensively.
# that verify this extensively.
self
.
assertEqual
(
xblock
.
title
,
u'Foo'
)
self
.
assertEqual
(
xblock
.
title
,
data
[
'settings'
][
'title'
]
)
self
.
assertEqual
(
xblock
.
prompt
,
u'Test prompt'
)
self
.
assertEqual
(
xblock
.
prompt
,
data
[
'prompt'
]
)
self
.
assertEqual
(
xblock
.
rubric_assessments
[
0
][
'name'
],
'peer-assessment'
)
self
.
assertEqual
(
xblock
.
rubric_assessments
[
0
][
'name'
],
data
[
'expected-assessment'
]
)
self
.
assertEqual
(
xblock
.
rubric_criteria
[
0
][
'prompt'
],
'Test criterion prompt'
)
self
.
assertEqual
(
xblock
.
rubric_criteria
[
0
][
'prompt'
],
data
[
'expected-criterion-prompt'
]
)
@file_data
(
'data/update_xblock.json'
)
@scenario
(
'data/basic_scenario.xml'
)
@scenario
(
'data/basic_scenario.xml'
)
def
test_update_xml_post_release
(
self
,
xblock
):
def
test_update_context_post_release
(
self
,
xblock
,
data
):
# First, parse XML data into a single string.
data
[
'rubric'
]
=
""
.
join
(
data
[
'rubric'
])
data
[
'settings'
][
'assessments'
]
=
""
.
join
(
data
[
'settings'
][
'assessments'
])
# XBlock start date defaults to already open,
# XBlock start date defaults to already open,
# so we should get an error when trying to update anything that change the number of points
# so we should get an error when trying to update anything that change the number of points
request
=
json
.
dumps
(
{
'xml'
:
self
.
load_fixture_str
(
'data/updated_block.xml'
)}
)
request
=
json
.
dumps
(
data
)
# Verify the response is successfully
# Verify the response is successfully
resp
=
self
.
request
(
xblock
,
'update_
xml
'
,
request
,
response_format
=
'json'
)
resp
=
self
.
request
(
xblock
,
'update_
editor_context
'
,
request
,
response_format
=
'json'
)
self
.
assertFalse
(
resp
[
'success'
])
self
.
assertFalse
(
resp
[
'success'
])
@file_data
(
'data/invalid_update_xblock.json'
)
@scenario
(
'data/basic_scenario.xml'
)
@scenario
(
'data/basic_scenario.xml'
)
def
test_update_
xml_invalid_request_data
(
self
,
xblock
):
def
test_update_
context_invalid_request_data
(
self
,
xblock
,
data
):
resp
=
self
.
request
(
xblock
,
'update_xml'
,
json
.
dumps
({}),
response_format
=
'json'
)
# First, parse XML data into a single string.
self
.
assertFalse
(
resp
[
'success'
])
if
'rubric'
in
data
:
self
.
assertIn
(
'xml'
,
resp
[
'msg'
]
.
lower
()
)
data
[
'rubric'
]
=
""
.
join
(
data
[
'rubric'
]
)
@scenario
(
'data/basic_scenario.xml'
)
if
'settings'
in
data
and
'assessments'
in
data
[
'settings'
]:
def
test_update_xml_invalid_date_format
(
self
,
xblock
):
data
[
'settings'
][
'assessments'
]
=
""
.
join
(
data
[
'settings'
][
'assessments'
])
request
=
json
.
dumps
({
'xml'
:
self
.
load_fixture_str
(
'data/invalid_dates.xml'
)})
resp
=
self
.
request
(
xblock
,
'update_xml'
,
request
,
response_format
=
'json'
)
self
.
assertFalse
(
resp
[
'success'
])
self
.
assertIn
(
"cannot be later than"
,
resp
[
'msg'
]
.
lower
())
# Test that we enforce that there are exactly two assessments,
xblock
.
published_date
=
None
# peer ==> self
# If and when we remove this restriction, this test can be deleted.
resp
=
self
.
request
(
xblock
,
'update_editor_context'
,
json
.
dumps
(
data
),
response_format
=
'json'
)
@data
(
'data/invalid_assessment_combo_order.xml'
)
@scenario
(
'data/basic_scenario.xml'
)
def
test_update_xml_invalid_assessment_combo
(
self
,
xblock
,
invalid_workflow
):
request
=
json
.
dumps
(
{
'xml'
:
self
.
load_fixture_str
(
invalid_workflow
)}
)
resp
=
self
.
request
(
xblock
,
'update_xml'
,
request
,
response_format
=
'json'
)
self
.
assertFalse
(
resp
[
'success'
])
self
.
assertFalse
(
resp
[
'success'
])
self
.
assertIn
(
"for this assignment"
,
resp
[
'msg'
]
.
lower
())
self
.
assertIn
(
data
[
'expected_error'
]
,
resp
[
'msg'
]
.
lower
())
@
data
((
'data/invalid_rubric.xml'
,
'rubric'
),
(
'data/invalid_assessment.xml'
,
'assessment'
)
)
@
file_data
(
'data/invalid_rubric.json'
)
@scenario
(
'data/basic_scenario.xml'
)
@scenario
(
'data/basic_scenario.xml'
)
def
test_update_xml_invalid
(
self
,
xblock
,
data
):
def
test_update_rubric_invalid
(
self
,
xblock
,
data
):
xml_path
=
data
[
0
]
# First, parse XML data into a single string.
expected_msg
=
data
[
1
]
data
[
'rubric'
]
=
""
.
join
(
data
[
'rubric'
])
data
[
'settings'
][
'assessments'
]
=
""
.
join
(
data
[
'settings'
][
'assessments'
])
request
=
json
.
dumps
(
{
'xml'
:
self
.
load_fixture_str
(
xml_path
)}
)
request
=
json
.
dumps
(
data
)
# Store old XBlock fields for later verification
# Store old XBlock fields for later verification
old_title
=
xblock
.
title
old_title
=
xblock
.
title
...
@@ -117,9 +118,9 @@ class StudioViewTest(XBlockHandlerTestCase):
...
@@ -117,9 +118,9 @@ class StudioViewTest(XBlockHandlerTestCase):
old_criteria
=
xblock
.
rubric_criteria
old_criteria
=
xblock
.
rubric_criteria
# Verify the response fails
# Verify the response fails
resp
=
self
.
request
(
xblock
,
'update_
xml
'
,
request
,
response_format
=
'json'
)
resp
=
self
.
request
(
xblock
,
'update_
editor_context
'
,
request
,
response_format
=
'json'
)
self
.
assertFalse
(
resp
[
'success'
])
self
.
assertFalse
(
resp
[
'success'
])
self
.
assertIn
(
expected_msg
,
resp
[
'msg'
]
.
lower
())
self
.
assertIn
(
"not valid"
,
resp
[
'msg'
]
.
lower
())
# Check that the XBlock fields were NOT updated
# Check that the XBlock fields were NOT updated
# We don't need to be exhaustive here, because we have other unit tests
# We don't need to be exhaustive here, because we have other unit tests
...
...
openassessment/xblock/test/test_xml.py
View file @
a83b25cf
...
@@ -12,7 +12,10 @@ from django.test import TestCase
...
@@ -12,7 +12,10 @@ from django.test import TestCase
import
ddt
import
ddt
from
openassessment.xblock.openassessmentblock
import
OpenAssessmentBlock
from
openassessment.xblock.openassessmentblock
import
OpenAssessmentBlock
from
openassessment.xblock.xml
import
(
from
openassessment.xblock.xml
import
(
serialize_content
,
update_from_xml_str
,
ValidationError
,
UpdateFromXmlError
serialize_content
,
parse_from_xml_str
,
parse_rubric_xml_str
,
parse_examples_xml_str
,
parse_assessments_xml_str
,
serialize_rubric_to_xml_str
,
serialize_examples_to_xml_str
,
serialize_assessments_to_xml_str
,
UpdateFromXmlError
)
)
...
@@ -91,8 +94,8 @@ class TestSerializeContent(TestCase):
...
@@ -91,8 +94,8 @@ class TestSerializeContent(TestCase):
"""
"""
self
.
oa_block
=
mock
.
MagicMock
(
OpenAssessmentBlock
)
self
.
oa_block
=
mock
.
MagicMock
(
OpenAssessmentBlock
)
@ddt.file_data
(
'data/serialize.json'
)
def
test_serialize
(
self
,
data
):
def
_configure_xblock
(
self
,
data
):
self
.
oa_block
.
title
=
data
[
'title'
]
self
.
oa_block
.
title
=
data
[
'title'
]
self
.
oa_block
.
prompt
=
data
[
'prompt'
]
self
.
oa_block
.
prompt
=
data
[
'prompt'
]
self
.
oa_block
.
rubric_feedback_prompt
=
data
[
'rubric_feedback_prompt'
]
self
.
oa_block
.
rubric_feedback_prompt
=
data
[
'rubric_feedback_prompt'
]
...
@@ -102,6 +105,10 @@ class TestSerializeContent(TestCase):
...
@@ -102,6 +105,10 @@ class TestSerializeContent(TestCase):
self
.
oa_block
.
submission_due
=
data
[
'submission_due'
]
self
.
oa_block
.
submission_due
=
data
[
'submission_due'
]
self
.
oa_block
.
rubric_criteria
=
data
[
'criteria'
]
self
.
oa_block
.
rubric_criteria
=
data
[
'criteria'
]
self
.
oa_block
.
rubric_assessments
=
data
[
'assessments'
]
self
.
oa_block
.
rubric_assessments
=
data
[
'assessments'
]
@ddt.file_data
(
'data/serialize.json'
)
def
test_serialize
(
self
,
data
):
self
.
_configure_xblock
(
data
)
xml
=
serialize_content
(
self
.
oa_block
)
xml
=
serialize_content
(
self
.
oa_block
)
# Compare the XML with our expected output
# Compare the XML with our expected output
...
@@ -144,6 +151,23 @@ class TestSerializeContent(TestCase):
...
@@ -144,6 +151,23 @@ class TestSerializeContent(TestCase):
)
)
)
)
@ddt.file_data
(
'data/serialize.json'
)
def
test_serialize_rubric
(
self
,
data
):
self
.
_configure_xblock
(
data
)
xml_str
=
serialize_rubric_to_xml_str
(
self
.
oa_block
)
@ddt.file_data
(
'data/serialize.json'
)
def
test_serialize_examples
(
self
,
data
):
self
.
_configure_xblock
(
data
)
for
assessment
in
data
[
'assessments'
]:
if
'student-training'
==
assessment
[
'name'
]:
xml_str
=
serialize_examples_to_xml_str
(
assessment
)
@ddt.file_data
(
'data/serialize.json'
)
def
test_serialize_assessments
(
self
,
data
):
self
.
_configure_xblock
(
data
)
xml_str
=
serialize_assessments_to_xml_str
(
self
.
oa_block
)
def
test_mutated_criteria_dict
(
self
):
def
test_mutated_criteria_dict
(
self
):
self
.
oa_block
.
title
=
"Test title"
self
.
oa_block
.
title
=
"Test title"
self
.
oa_block
.
rubric_assessments
=
self
.
BASIC_ASSESSMENTS
self
.
oa_block
.
rubric_assessments
=
self
.
BASIC_ASSESSMENTS
...
@@ -300,6 +324,36 @@ class TestSerializeContent(TestCase):
...
@@ -300,6 +324,36 @@ class TestSerializeContent(TestCase):
mutated
[
key
]
=
new_val
mutated
[
key
]
=
new_val
return
mutated
return
mutated
@ddt.ddt
class
TestParseRubricFromXml
(
TestCase
):
@ddt.file_data
(
"data/parse_rubric_xml.json"
)
def
test_parse_rubric_from_xml
(
self
,
data
):
rubric
=
parse_rubric_xml_str
(
""
.
join
(
data
[
'xml'
]))
self
.
assertEqual
(
rubric
[
'prompt'
],
data
[
'prompt'
])
self
.
assertEqual
(
rubric
[
'feedbackprompt'
],
data
[
'feedbackprompt'
])
self
.
assertEqual
(
rubric
[
'criteria'
],
data
[
'criteria'
])
@ddt.ddt
class
TestParseExamplesFromXml
(
TestCase
):
@ddt.file_data
(
"data/parse_examples_xml.json"
)
def
test_parse_examples_from_xml
(
self
,
data
):
examples
=
parse_examples_xml_str
(
""
.
join
(
data
[
'xml'
]))
self
.
assertEqual
(
examples
,
data
[
'examples'
])
@ddt.ddt
class
TestParseAssessmentsFromXml
(
TestCase
):
@ddt.file_data
(
"data/parse_assessments_xml.json"
)
def
test_parse_assessments_from_xml
(
self
,
data
):
assessments
=
parse_assessments_xml_str
(
""
.
join
(
data
[
'xml'
]))
self
.
assertEqual
(
assessments
,
data
[
'assessments'
])
@ddt.ddt
@ddt.ddt
class
TestUpdateFromXml
(
TestCase
):
class
TestUpdateFromXml
(
TestCase
):
...
@@ -324,36 +378,20 @@ class TestUpdateFromXml(TestCase):
...
@@ -324,36 +378,20 @@ class TestUpdateFromXml(TestCase):
self
.
oa_block
.
submission_due
=
"2000-01-01T00:00:00"
self
.
oa_block
.
submission_due
=
"2000-01-01T00:00:00"
@ddt.file_data
(
'data/update_from_xml.json'
)
@ddt.file_data
(
'data/update_from_xml.json'
)
def
test_
updat
e_from_xml
(
self
,
data
):
def
test_
pars
e_from_xml
(
self
,
data
):
# Update the block based on the fixture XML definition
# Update the block based on the fixture XML definition
returned_block
=
update_from_xml_str
(
self
.
oa_block
,
""
.
join
(
data
[
'xml'
]))
config
=
parse_from_xml_str
(
""
.
join
(
data
[
'xml'
]))
# The block we passed in should be updated and returned
self
.
assertEqual
(
self
.
oa_block
,
returned_block
)
# Check that the contents of the modified XBlock are correct
# Check that the contents of the modified XBlock are correct
self
.
assertEqual
(
self
.
oa_block
.
title
,
data
[
'title'
])
self
.
assertEqual
(
config
[
'title'
],
data
[
'title'
])
self
.
assertEqual
(
self
.
oa_block
.
prompt
,
data
[
'prompt'
])
self
.
assertEqual
(
config
[
'prompt'
],
data
[
'prompt'
])
self
.
assertEqual
(
self
.
oa_block
.
start
,
_parse_date
(
data
[
'start'
]))
self
.
assertEqual
(
config
[
'submission_start'
],
data
[
'submission_start'
])
self
.
assertEqual
(
self
.
oa_block
.
due
,
_parse_date
(
data
[
'due'
]))
self
.
assertEqual
(
config
[
'submission_due'
],
data
[
'submission_due'
])
self
.
assertEqual
(
self
.
oa_block
.
submission_start
,
data
[
'submission_start'
])
self
.
assertEqual
(
config
[
'rubric_criteria'
],
data
[
'criteria'
])
self
.
assertEqual
(
self
.
oa_block
.
submission_due
,
data
[
'submission_due'
])
self
.
assertEqual
(
config
[
'rubric_assessments'
],
data
[
'assessments'
])
self
.
assertEqual
(
self
.
oa_block
.
rubric_criteria
,
data
[
'criteria'
])
self
.
assertEqual
(
self
.
oa_block
.
rubric_assessments
,
data
[
'assessments'
])
@ddt.file_data
(
'data/update_from_xml_error.json'
)
@ddt.file_data
(
'data/update_from_xml_error.json'
)
def
test_
updat
e_from_xml_error
(
self
,
data
):
def
test_
pars
e_from_xml_error
(
self
,
data
):
with
self
.
assertRaises
(
UpdateFromXmlError
):
with
self
.
assertRaises
(
UpdateFromXmlError
):
update_from_xml_str
(
self
.
oa_block
,
""
.
join
(
data
[
'xml'
]))
parse_from_xml_str
(
""
.
join
(
data
[
'xml'
]))
@ddt.file_data
(
'data/update_from_xml.json'
)
def
test_invalid
(
self
,
data
):
# Plug in a rubric validator that always reports that the rubric dict is invalid.
# We need to back this up with an integration test that checks whether the XBlock
# provides an appropriate rubric validator.
with
self
.
assertRaises
(
ValidationError
):
update_from_xml_str
(
self
.
oa_block
,
""
.
join
(
data
[
'xml'
]),
validator
=
lambda
*
args
:
(
False
,
''
)
)
openassessment/xblock/xml.py
View file @
a83b25cf
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment