Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
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-platform
Commits
68cf4c45
Commit
68cf4c45
authored
Feb 28, 2013
by
Will Daly
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added tests for HTMl rendering of problems
Added support for rendering response messages
parent
9f6119a1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
345 additions
and
3 deletions
+345
-3
common/lib/capa/capa/capa_problem.py
+3
-1
common/lib/capa/capa/responsetypes.py
+10
-2
common/lib/capa/capa/tests/test_correctmap.py
+146
-0
common/lib/capa/capa/tests/test_html_render.py
+186
-0
No files found.
common/lib/capa/capa/capa_problem.py
View file @
68cf4c45
...
...
@@ -510,7 +510,9 @@ class LoncapaProblem(object):
# let each Response render itself
if
problemtree
in
self
.
responders
:
return
self
.
responders
[
problemtree
]
.
render_html
(
self
.
_extract_html
)
overall_msg
=
self
.
correct_map
.
get_overall_message
()
return
self
.
responders
[
problemtree
]
.
render_html
(
self
.
_extract_html
,
response_msg
=
overall_msg
)
# let each custom renderer render itself:
if
problemtree
.
tag
in
customrender
.
registry
.
registered_tags
():
...
...
common/lib/capa/capa/responsetypes.py
View file @
68cf4c45
...
...
@@ -174,13 +174,14 @@ class LoncapaResponse(object):
'''
return
sum
(
self
.
maxpoints
.
values
())
def
render_html
(
self
,
renderer
):
def
render_html
(
self
,
renderer
,
response_msg
=
None
):
'''
Return XHTML Element tree representation of this Response.
Arguments:
- renderer : procedure which produces HTML given an ElementTree
- response_msg: a message displayed at the end of the Response
'''
# render ourself as a <span> + our content
tree
=
etree
.
Element
(
'span'
)
...
...
@@ -195,6 +196,13 @@ class LoncapaResponse(object):
if
item_xhtml
is
not
None
:
tree
.
append
(
item_xhtml
)
tree
.
tail
=
self
.
xml
.
tail
# Add a <div> for the message at the end of the response
if
response_msg
:
response_msg_div
=
etree
.
SubElement
(
tree
,
'div'
)
response_msg_div
.
set
(
"class"
,
"response_message"
)
response_msg_div
.
text
=
response_msg
return
tree
def
evaluate_answers
(
self
,
student_answers
,
old_cmap
):
...
...
@@ -1060,7 +1068,7 @@ def sympy_check2():
# and the first input stores the message
if
'ok'
in
ret
:
correct
=
[
'correct'
]
*
len
(
idset
)
if
ret
[
'ok'
]
else
[
'incorrect'
]
*
len
(
idset
)
msg
=
ret
[
'msg'
]
msg
=
ret
.
get
(
'msg'
,
None
)
if
1
:
# try to clean up message html
...
...
common/lib/capa/capa/tests/test_correctmap.py
0 → 100644
View file @
68cf4c45
import
unittest
from
capa.correctmap
import
CorrectMap
import
datetime
class
CorrectMapTest
(
unittest
.
TestCase
):
def
setUp
(
self
):
self
.
cmap
=
CorrectMap
()
def
test_set_input_properties
(
self
):
# Set the correctmap properties for two inputs
self
.
cmap
.
set
(
answer_id
=
'1_2_1'
,
correctness
=
'correct'
,
npoints
=
5
,
msg
=
'Test message'
,
hint
=
'Test hint'
,
hintmode
=
'always'
,
queuestate
=
{
'key'
:
'secretstring'
,
'time'
:
'20130228100026'
})
self
.
cmap
.
set
(
answer_id
=
'2_2_1'
,
correctness
=
'incorrect'
,
npoints
=
None
,
msg
=
None
,
hint
=
None
,
hintmode
=
None
,
queuestate
=
None
)
# Assert that each input has the expected properties
self
.
assertTrue
(
self
.
cmap
.
is_correct
(
'1_2_1'
))
self
.
assertFalse
(
self
.
cmap
.
is_correct
(
'2_2_1'
))
self
.
assertEqual
(
self
.
cmap
.
get_correctness
(
'1_2_1'
),
'correct'
)
self
.
assertEqual
(
self
.
cmap
.
get_correctness
(
'2_2_1'
),
'incorrect'
)
self
.
assertEqual
(
self
.
cmap
.
get_npoints
(
'1_2_1'
),
5
)
self
.
assertEqual
(
self
.
cmap
.
get_npoints
(
'2_2_1'
),
0
)
self
.
assertEqual
(
self
.
cmap
.
get_msg
(
'1_2_1'
),
'Test message'
)
self
.
assertEqual
(
self
.
cmap
.
get_msg
(
'2_2_1'
),
None
)
self
.
assertEqual
(
self
.
cmap
.
get_hint
(
'1_2_1'
),
'Test hint'
)
self
.
assertEqual
(
self
.
cmap
.
get_hint
(
'2_2_1'
),
None
)
self
.
assertEqual
(
self
.
cmap
.
get_hintmode
(
'1_2_1'
),
'always'
)
self
.
assertEqual
(
self
.
cmap
.
get_hintmode
(
'2_2_1'
),
None
)
self
.
assertTrue
(
self
.
cmap
.
is_queued
(
'1_2_1'
))
self
.
assertFalse
(
self
.
cmap
.
is_queued
(
'2_2_1'
))
self
.
assertEqual
(
self
.
cmap
.
get_queuetime_str
(
'1_2_1'
),
'20130228100026'
)
self
.
assertEqual
(
self
.
cmap
.
get_queuetime_str
(
'2_2_1'
),
None
)
self
.
assertTrue
(
self
.
cmap
.
is_right_queuekey
(
'1_2_1'
,
'secretstring'
))
self
.
assertFalse
(
self
.
cmap
.
is_right_queuekey
(
'1_2_1'
,
'invalidstr'
))
self
.
assertFalse
(
self
.
cmap
.
is_right_queuekey
(
'1_2_1'
,
''
))
self
.
assertFalse
(
self
.
cmap
.
is_right_queuekey
(
'1_2_1'
,
None
))
self
.
assertFalse
(
self
.
cmap
.
is_right_queuekey
(
'2_2_1'
,
'secretstring'
))
self
.
assertFalse
(
self
.
cmap
.
is_right_queuekey
(
'2_2_1'
,
'invalidstr'
))
self
.
assertFalse
(
self
.
cmap
.
is_right_queuekey
(
'2_2_1'
,
''
))
self
.
assertFalse
(
self
.
cmap
.
is_right_queuekey
(
'2_2_1'
,
None
))
def
test_get_npoints
(
self
):
# Set the correctmap properties for 4 inputs
# 1) correct, 5 points
# 2) correct, None points
# 3) incorrect, 5 points
# 4) incorrect, None points
self
.
cmap
.
set
(
answer_id
=
'1_2_1'
,
correctness
=
'correct'
,
npoints
=
5
)
self
.
cmap
.
set
(
answer_id
=
'2_2_1'
,
correctness
=
'correct'
,
npoints
=
None
)
self
.
cmap
.
set
(
answer_id
=
'3_2_1'
,
correctness
=
'incorrect'
,
npoints
=
5
)
self
.
cmap
.
set
(
answer_id
=
'4_2_1'
,
correctness
=
'incorrect'
,
npoints
=
None
)
# Assert that we get the expected points
# If points assigned and correct --> npoints
# If no points assigned and correct --> 1 point
# Otherwise --> 0 points
self
.
assertEqual
(
self
.
cmap
.
get_npoints
(
'1_2_1'
),
5
)
self
.
assertEqual
(
self
.
cmap
.
get_npoints
(
'2_2_1'
),
1
)
self
.
assertEqual
(
self
.
cmap
.
get_npoints
(
'3_2_1'
),
0
)
self
.
assertEqual
(
self
.
cmap
.
get_npoints
(
'4_2_1'
),
0
)
def
test_set_overall_message
(
self
):
# Default is an empty string string
self
.
assertEqual
(
self
.
cmap
.
get_overall_message
(),
""
)
# Set a message that applies to the whole question
self
.
cmap
.
set_overall_message
(
"Test message"
)
# Retrieve the message
self
.
assertEqual
(
self
.
cmap
.
get_overall_message
(),
"Test message"
)
# Setting the message to None --> empty string
self
.
cmap
.
set_overall_message
(
None
)
self
.
assertEqual
(
self
.
cmap
.
get_overall_message
(),
""
)
def
test_update_from_correctmap
(
self
):
# Initialize a CorrectMap with some properties
self
.
cmap
.
set
(
answer_id
=
'1_2_1'
,
correctness
=
'correct'
,
npoints
=
5
,
msg
=
'Test message'
,
hint
=
'Test hint'
,
hintmode
=
'always'
,
queuestate
=
{
'key'
:
'secretstring'
,
'time'
:
'20130228100026'
})
self
.
cmap
.
set_overall_message
(
"Test message"
)
# Create a second cmap, then update it to have the same properties
# as the first cmap
other_cmap
=
CorrectMap
()
other_cmap
.
update
(
self
.
cmap
)
# Assert that it has all the same properties
self
.
assertEqual
(
other_cmap
.
get_overall_message
(),
self
.
cmap
.
get_overall_message
())
self
.
assertEqual
(
other_cmap
.
get_dict
(),
self
.
cmap
.
get_dict
())
def
test_update_from_invalid
(
self
):
# Should get an exception if we try to update() a CorrectMap
# with a non-CorrectMap value
invalid_list
=
[
None
,
"string"
,
5
,
datetime
.
datetime
.
today
()]
for
invalid
in
invalid_list
:
with
self
.
assertRaises
(
Exception
):
self
.
cmap
.
update
(
invalid
)
common/lib/capa/capa/tests/test_html_render.py
0 → 100644
View file @
68cf4c45
import
unittest
from
lxml
import
etree
import
os
import
textwrap
import
json
import
mock
from
capa.capa_problem
import
LoncapaProblem
from
response_xml_factory
import
StringResponseXMLFactory
,
CustomResponseXMLFactory
from
.
import
test_system
class
CapaHtmlRenderTest
(
unittest
.
TestCase
):
def
test_include_html
(
self
):
# Create a test file to include
self
.
_create_test_file
(
'test_include.xml'
,
'<test>Test include</test>'
)
# Generate some XML with an <include>
xml_str
=
textwrap
.
dedent
(
"""
<problem>
<include file="test_include.xml"/>
</problem>
"""
)
# Create the problem
problem
=
LoncapaProblem
(
xml_str
,
'1'
,
system
=
test_system
)
# Render the HTML
rendered_html
=
etree
.
XML
(
problem
.
get_html
())
# Expect that the include file was embedded in the problem
test_element
=
rendered_html
.
find
(
"test"
)
self
.
assertEqual
(
test_element
.
tag
,
"test"
)
self
.
assertEqual
(
test_element
.
text
,
"Test include"
)
def
test_process_outtext
(
self
):
# Generate some XML with <startouttext /> and <endouttext />
xml_str
=
textwrap
.
dedent
(
"""
<problem>
<startouttext/>Test text<endouttext/>
</problem>
"""
)
# Create the problem
problem
=
LoncapaProblem
(
xml_str
,
'1'
,
system
=
test_system
)
# Render the HTML
rendered_html
=
etree
.
XML
(
problem
.
get_html
())
# Expect that the <startouttext /> and <endouttext />
# were converted to <span></span> tags
span_element
=
rendered_html
.
find
(
'span'
)
self
.
assertEqual
(
span_element
.
text
,
'Test text'
)
def
test_render_script
(
self
):
# Generate some XML with a <script> tag
xml_str
=
textwrap
.
dedent
(
"""
<problem>
<script>test=True</script>
</problem>
"""
)
# Create the problem
problem
=
LoncapaProblem
(
xml_str
,
'1'
,
system
=
test_system
)
# Render the HTML
rendered_html
=
etree
.
XML
(
problem
.
get_html
())
# Expect that the script element has been removed from the rendered HTML
script_element
=
rendered_html
.
find
(
'script'
)
self
.
assertEqual
(
None
,
script_element
)
def
test_render_response_xml
(
self
):
# Generate some XML for a string response
kwargs
=
{
'question_text'
:
"Test question"
,
'explanation_text'
:
"Test explanation"
,
'answer'
:
'Test answer'
,
'hints'
:
[(
'test prompt'
,
'test_hint'
,
'test hint text'
)]}
xml_str
=
StringResponseXMLFactory
()
.
build_xml
(
**
kwargs
)
# Mock out the template renderer
test_system
.
render_template
=
mock
.
Mock
()
test_system
.
render_template
.
return_value
=
"<div>Input Template Render</div>"
# Create the problem and render the HTML
problem
=
LoncapaProblem
(
xml_str
,
'1'
,
system
=
test_system
)
rendered_html
=
etree
.
XML
(
problem
.
get_html
())
# Expect problem has been turned into a <div>
self
.
assertEqual
(
rendered_html
.
tag
,
"div"
)
# Expect question text is in a <p> child
question_element
=
rendered_html
.
find
(
"p"
)
self
.
assertEqual
(
question_element
.
text
,
"Test question"
)
# Expect that the response has been turned into a <span>
response_element
=
rendered_html
.
find
(
"span"
)
self
.
assertEqual
(
response_element
.
tag
,
"span"
)
# Expect that the response <span>
# that contains a <div> for the textline
textline_element
=
response_element
.
find
(
"div"
)
self
.
assertEqual
(
textline_element
.
text
,
'Input Template Render'
)
# Expect a child <div> for the solution
# with the rendered template
solution_element
=
rendered_html
.
find
(
"div"
)
self
.
assertEqual
(
solution_element
.
text
,
'Input Template Render'
)
# Expect that the template renderer was called with the correct
# arguments, once for the textline input and once for
# the solution
expected_textline_context
=
{
'status'
:
'unsubmitted'
,
'value'
:
''
,
'preprocessor'
:
None
,
'msg'
:
''
,
'inline'
:
False
,
'hidden'
:
False
,
'do_math'
:
False
,
'id'
:
'1_2_1'
,
'size'
:
None
}
expected_solution_context
=
{
'id'
:
'1_solution_1'
}
expected_calls
=
[
mock
.
call
(
'textline.html'
,
expected_textline_context
),
mock
.
call
(
'solutionspan.html'
,
expected_solution_context
)]
self
.
assertEqual
(
test_system
.
render_template
.
call_args_list
,
expected_calls
)
def
test_render_response_with_overall_msg
(
self
):
# CustomResponse script that sets an overall_message
script
=
textwrap
.
dedent
(
"""
def check_func(*args):
return {'overall_message': 'Test message',
'input_list': [ {'ok': True, 'msg': '' } ] }
"""
)
# Generate some XML for a CustomResponse
kwargs
=
{
'script'
:
script
,
'cfn'
:
'check_func'
}
xml_str
=
CustomResponseXMLFactory
()
.
build_xml
(
**
kwargs
)
# Create the problem and render the html
problem
=
LoncapaProblem
(
xml_str
,
'1'
,
system
=
test_system
)
# Grade the problem
correctmap
=
problem
.
grade_answers
({
'1_2_1'
:
'test'
})
# Render the html
rendered_html
=
etree
.
XML
(
problem
.
get_html
())
# Expect that there is a <div> within the response <div>
# with css class response_message
msg_div_element
=
rendered_html
.
find
(
".//div[@class='response_message']"
)
self
.
assertEqual
(
msg_div_element
.
tag
,
"div"
)
self
.
assertEqual
(
msg_div_element
.
get
(
'class'
),
"response_message"
)
def
test_substitute_python_vars
(
self
):
# Generate some XML with Python variables defined in a script
# and used later as attributes
xml_str
=
textwrap
.
dedent
(
"""
<problem>
<script>test="TEST"</script>
<span attr="$test"></span>
</problem>
"""
)
# Create the problem and render the HTML
problem
=
LoncapaProblem
(
xml_str
,
'1'
,
system
=
test_system
)
rendered_html
=
etree
.
XML
(
problem
.
get_html
())
# Expect that the variable $test has been replaced with its value
span_element
=
rendered_html
.
find
(
'span'
)
self
.
assertEqual
(
span_element
.
get
(
'attr'
),
"TEST"
)
def
_create_test_file
(
self
,
path
,
content_str
):
test_fp
=
test_system
.
filestore
.
open
(
path
,
"w"
)
test_fp
.
write
(
content_str
)
test_fp
.
close
()
self
.
addCleanup
(
lambda
:
os
.
remove
(
test_fp
.
name
))
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