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
c1324ec2
Commit
c1324ec2
authored
Feb 27, 2013
by
Will Daly
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Modified CodeResponse to use XML factory
parent
6e4c418a
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
92 additions
and
46 deletions
+92
-46
common/lib/capa/capa/tests/response_xml_factory.py
+55
-6
common/lib/capa/capa/tests/test_files/filename_convert_test.txt
+1
-0
common/lib/capa/capa/tests/test_responsetypes.py
+36
-40
No files found.
common/lib/capa/capa/tests/response_xml_factory.py
View file @
c1324ec2
...
@@ -43,6 +43,8 @@ class ResponseXMLFactory(object):
...
@@ -43,6 +43,8 @@ class ResponseXMLFactory(object):
*script*: The embedded Python script (a string)
*script*: The embedded Python script (a string)
*num_responses*: The number of responses to create [DEFAULT: 1]
*num_inputs*: The number of input elements
*num_inputs*: The number of input elements
to create [DEFAULT: 1]
to create [DEFAULT: 1]
...
@@ -53,6 +55,7 @@ class ResponseXMLFactory(object):
...
@@ -53,6 +55,7 @@ class ResponseXMLFactory(object):
question_text
=
kwargs
.
get
(
'question_text'
,
''
)
question_text
=
kwargs
.
get
(
'question_text'
,
''
)
explanation_text
=
kwargs
.
get
(
'explanation_text'
,
''
)
explanation_text
=
kwargs
.
get
(
'explanation_text'
,
''
)
script
=
kwargs
.
get
(
'script'
,
None
)
script
=
kwargs
.
get
(
'script'
,
None
)
num_responses
=
kwargs
.
get
(
'num_responses'
,
1
)
num_inputs
=
kwargs
.
get
(
'num_inputs'
,
1
)
num_inputs
=
kwargs
.
get
(
'num_inputs'
,
1
)
# The root is <problem>
# The root is <problem>
...
@@ -68,16 +71,19 @@ class ResponseXMLFactory(object):
...
@@ -68,16 +71,19 @@ class ResponseXMLFactory(object):
question
=
etree
.
SubElement
(
root
,
"p"
)
question
=
etree
.
SubElement
(
root
,
"p"
)
question
.
text
=
question_text
question
.
text
=
question_text
# Add the response
# Add the response(s)
for
i
in
range
(
0
,
int
(
num_responses
)):
response_element
=
self
.
create_response_element
(
**
kwargs
)
response_element
=
self
.
create_response_element
(
**
kwargs
)
root
.
append
(
response_element
)
root
.
append
(
response_element
)
# Add input elements
# Add input elements
for
i
in
range
(
0
,
int
(
num_inputs
)):
for
j
in
range
(
0
,
int
(
num_inputs
)):
input_element
=
self
.
create_input_element
(
**
kwargs
)
input_element
=
self
.
create_input_element
(
**
kwargs
)
if
not
(
None
==
input_element
):
response_element
.
append
(
input_element
)
response_element
.
append
(
input_element
)
# The problem has an explanation of the solution
# The problem has an explanation of the solution
if
explanation_text
:
explanation
=
etree
.
SubElement
(
root
,
"solution"
)
explanation
=
etree
.
SubElement
(
root
,
"solution"
)
explanation_div
=
etree
.
SubElement
(
explanation
,
"div"
)
explanation_div
=
etree
.
SubElement
(
explanation
,
"div"
)
explanation_div
.
set
(
"class"
,
"detailed-solution"
)
explanation_div
.
set
(
"class"
,
"detailed-solution"
)
...
@@ -271,13 +277,56 @@ class SchematicResponseXMLFactory(ResponseXMLFactory):
...
@@ -271,13 +277,56 @@ class SchematicResponseXMLFactory(ResponseXMLFactory):
class
CodeResponseXMLFactory
(
ResponseXMLFactory
):
class
CodeResponseXMLFactory
(
ResponseXMLFactory
):
""" Factory for creating <coderesponse> XML trees """
""" Factory for creating <coderesponse> XML trees """
def
build_xml
(
self
,
**
kwargs
):
# Since we are providing an <answer> tag,
# we should override the default behavior
# of including a <solution> tag as well
kwargs
[
'explanation_text'
]
=
None
return
super
(
CodeResponseXMLFactory
,
self
)
.
build_xml
(
**
kwargs
)
def
create_response_element
(
self
,
**
kwargs
):
def
create_response_element
(
self
,
**
kwargs
):
""" Create a <coderesponse> XML element """
""" Create a <coderesponse> XML element:
raise
NotImplemented
def
create_input_element
(
self
,
**
kwargs
):
Uses **kwargs:
raise
NotImplemented
*initial_display*: The code that initially appears in the textbox
[DEFAULT: "Enter code here"]
*answer_display*: The answer to display to the student
[DEFAULT: "This is the correct answer!"]
*grader_payload*: A JSON-encoded string sent to the grader
[DEFAULT: empty dict string]
"""
# Get **kwargs
initial_display
=
kwargs
.
get
(
"initial_display"
,
"Enter code here"
)
answer_display
=
kwargs
.
get
(
"answer_display"
,
"This is the correct answer!"
)
grader_payload
=
kwargs
.
get
(
"grader_payload"
,
'{}'
)
# Create the <coderesponse> element
response_element
=
etree
.
Element
(
"coderesponse"
)
codeparam_element
=
etree
.
SubElement
(
response_element
,
"codeparam"
)
# Set the initial display text
initial_element
=
etree
.
SubElement
(
codeparam_element
,
"initial_display"
)
initial_element
.
text
=
str
(
initial_display
)
# Set the answer display text
answer_element
=
etree
.
SubElement
(
codeparam_element
,
"answer_display"
)
answer_element
.
text
=
str
(
answer_display
)
# Set the grader payload string
grader_element
=
etree
.
SubElement
(
codeparam_element
,
"grader_payload"
)
grader_element
.
text
=
str
(
grader_payload
)
# Create the input within the response
input_element
=
etree
.
SubElement
(
response_element
,
"textbox"
)
input_element
.
set
(
"mode"
,
"python"
)
return
response_element
def
create_input_element
(
self
,
**
kwargs
):
# Since we create this in create_response_element(),
# return None here
return
None
class
ChoiceResponseXMLFactory
(
ResponseXMLFactory
):
class
ChoiceResponseXMLFactory
(
ResponseXMLFactory
):
""" Factory for creating <choiceresponse> XML trees """
""" Factory for creating <choiceresponse> XML trees """
...
...
common/lib/capa/capa/tests/test_files/filename_convert_test.txt
0 → 100644
View file @
c1324ec2
This file is used to test converting file handles to filenames in the capa utility module
common/lib/capa/capa/tests/test_responsetypes.py
View file @
c1324ec2
...
@@ -399,11 +399,19 @@ class StringResponseTest(ResponseTest):
...
@@ -399,11 +399,19 @@ class StringResponseTest(ResponseTest):
correct_map
=
problem
.
grade_answers
(
input_dict
)
correct_map
=
problem
.
grade_answers
(
input_dict
)
self
.
assertEquals
(
correct_map
.
get_hint
(
'1_2_1'
),
""
)
self
.
assertEquals
(
correct_map
.
get_hint
(
'1_2_1'
),
""
)
class
CodeResponseTest
(
unittest
.
TestCase
):
class
CodeResponseTest
(
ResponseTest
):
'''
from
response_xml_factory
import
CodeResponseXMLFactory
Test CodeResponse
xml_factory_class
=
CodeResponseXMLFactory
TODO: Add tests for external grader messages
'''
def
setUp
(
self
):
super
(
CodeResponseTest
,
self
)
.
setUp
()
grader_payload
=
json
.
dumps
({
"grader"
:
"ps04/grade_square.py"
})
self
.
problem
=
self
.
build_problem
(
initial_display
=
"def square(x):"
,
answer_display
=
"answer"
,
grader_payload
=
grader_payload
,
num_responses
=
2
)
@staticmethod
@staticmethod
def
make_queuestate
(
key
,
time
):
def
make_queuestate
(
key
,
time
):
timestr
=
datetime
.
strftime
(
time
,
dateformat
)
timestr
=
datetime
.
strftime
(
time
,
dateformat
)
...
@@ -413,39 +421,32 @@ class CodeResponseTest(unittest.TestCase):
...
@@ -413,39 +421,32 @@ class CodeResponseTest(unittest.TestCase):
"""
"""
Simple test of whether LoncapaProblem knows when it's been queued
Simple test of whether LoncapaProblem knows when it's been queued
"""
"""
problem_file
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
"test_files/coderesponse.xml"
)
with
open
(
problem_file
)
as
input_file
:
test_lcp
=
lcp
.
LoncapaProblem
(
input_file
.
read
(),
'1'
,
system
=
test_system
)
answer_ids
=
sorted
(
test_lcp
.
get_question_answers
())
answer_ids
=
sorted
(
self
.
problem
.
get_question_answers
())
# CodeResponse requires internal CorrectMap state. Build it now in the unqueued state
# CodeResponse requires internal CorrectMap state. Build it now in the unqueued state
cmap
=
CorrectMap
()
cmap
=
CorrectMap
()
for
answer_id
in
answer_ids
:
for
answer_id
in
answer_ids
:
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_id
,
queuestate
=
None
))
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_id
,
queuestate
=
None
))
test_lcp
.
correct_map
.
update
(
cmap
)
self
.
problem
.
correct_map
.
update
(
cmap
)
self
.
assertEquals
(
test_lcp
.
is_queued
(),
False
)
self
.
assertEquals
(
self
.
problem
.
is_queued
(),
False
)
# Now we queue the LCP
# Now we queue the LCP
cmap
=
CorrectMap
()
cmap
=
CorrectMap
()
for
i
,
answer_id
in
enumerate
(
answer_ids
):
for
i
,
answer_id
in
enumerate
(
answer_ids
):
queuestate
=
CodeResponseTest
.
make_queuestate
(
i
,
datetime
.
now
())
queuestate
=
CodeResponseTest
.
make_queuestate
(
i
,
datetime
.
now
())
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_ids
[
i
],
queuestate
=
queuestate
))
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_ids
[
i
],
queuestate
=
queuestate
))
test_lcp
.
correct_map
.
update
(
cmap
)
self
.
problem
.
correct_map
.
update
(
cmap
)
self
.
assertEquals
(
test_lcp
.
is_queued
(),
True
)
self
.
assertEquals
(
self
.
problem
.
is_queued
(),
True
)
def
test_update_score
(
self
):
def
test_update_score
(
self
):
'''
'''
Test whether LoncapaProblem.update_score can deliver queued result to the right subproblem
Test whether LoncapaProblem.update_score can deliver queued result to the right subproblem
'''
'''
problem_file
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
"test_files/coderesponse.xml"
)
answer_ids
=
sorted
(
self
.
problem
.
get_question_answers
())
with
open
(
problem_file
)
as
input_file
:
test_lcp
=
lcp
.
LoncapaProblem
(
input_file
.
read
(),
'1'
,
system
=
test_system
)
answer_ids
=
sorted
(
test_lcp
.
get_question_answers
())
# CodeResponse requires internal CorrectMap state. Build it now in the queued state
# CodeResponse requires internal CorrectMap state. Build it now in the queued state
old_cmap
=
CorrectMap
()
old_cmap
=
CorrectMap
()
...
@@ -464,53 +465,49 @@ class CodeResponseTest(unittest.TestCase):
...
@@ -464,53 +465,49 @@ class CodeResponseTest(unittest.TestCase):
# Incorrect queuekey, state should not be updated
# Incorrect queuekey, state should not be updated
for
correctness
in
[
'correct'
,
'incorrect'
]:
for
correctness
in
[
'correct'
,
'incorrect'
]:
test_lcp
.
correct_map
=
CorrectMap
()
self
.
problem
.
correct_map
=
CorrectMap
()
test_lcp
.
correct_map
.
update
(
old_cmap
)
# Deep copy
self
.
problem
.
correct_map
.
update
(
old_cmap
)
# Deep copy
test_lcp
.
update_score
(
xserver_msgs
[
correctness
],
queuekey
=
0
)
self
.
problem
.
update_score
(
xserver_msgs
[
correctness
],
queuekey
=
0
)
self
.
assertEquals
(
test_lcp
.
correct_map
.
get_dict
(),
old_cmap
.
get_dict
())
# Deep comparison
self
.
assertEquals
(
self
.
problem
.
correct_map
.
get_dict
(),
old_cmap
.
get_dict
())
# Deep comparison
for
answer_id
in
answer_ids
:
for
answer_id
in
answer_ids
:
self
.
assertTrue
(
test_lcp
.
correct_map
.
is_queued
(
answer_id
))
# Should be still queued, since message undelivered
self
.
assertTrue
(
self
.
problem
.
correct_map
.
is_queued
(
answer_id
))
# Should be still queued, since message undelivered
# Correct queuekey, state should be updated
# Correct queuekey, state should be updated
for
correctness
in
[
'correct'
,
'incorrect'
]:
for
correctness
in
[
'correct'
,
'incorrect'
]:
for
i
,
answer_id
in
enumerate
(
answer_ids
):
for
i
,
answer_id
in
enumerate
(
answer_ids
):
test_lcp
.
correct_map
=
CorrectMap
()
self
.
problem
.
correct_map
=
CorrectMap
()
test_lcp
.
correct_map
.
update
(
old_cmap
)
self
.
problem
.
correct_map
.
update
(
old_cmap
)
new_cmap
=
CorrectMap
()
new_cmap
=
CorrectMap
()
new_cmap
.
update
(
old_cmap
)
new_cmap
.
update
(
old_cmap
)
npoints
=
1
if
correctness
==
'correct'
else
0
npoints
=
1
if
correctness
==
'correct'
else
0
new_cmap
.
set
(
answer_id
=
answer_id
,
npoints
=
npoints
,
correctness
=
correctness
,
msg
=
grader_msg
,
queuestate
=
None
)
new_cmap
.
set
(
answer_id
=
answer_id
,
npoints
=
npoints
,
correctness
=
correctness
,
msg
=
grader_msg
,
queuestate
=
None
)
test_lcp
.
update_score
(
xserver_msgs
[
correctness
],
queuekey
=
1000
+
i
)
self
.
problem
.
update_score
(
xserver_msgs
[
correctness
],
queuekey
=
1000
+
i
)
self
.
assertEquals
(
test_lcp
.
correct_map
.
get_dict
(),
new_cmap
.
get_dict
())
self
.
assertEquals
(
self
.
problem
.
correct_map
.
get_dict
(),
new_cmap
.
get_dict
())
for
j
,
test_id
in
enumerate
(
answer_ids
):
for
j
,
test_id
in
enumerate
(
answer_ids
):
if
j
==
i
:
if
j
==
i
:
self
.
assertFalse
(
test_lcp
.
correct_map
.
is_queued
(
test_id
))
# Should be dequeued, message delivered
self
.
assertFalse
(
self
.
problem
.
correct_map
.
is_queued
(
test_id
))
# Should be dequeued, message delivered
else
:
else
:
self
.
assertTrue
(
test_lcp
.
correct_map
.
is_queued
(
test_id
))
# Should be queued, message undelivered
self
.
assertTrue
(
self
.
problem
.
correct_map
.
is_queued
(
test_id
))
# Should be queued, message undelivered
def
test_recentmost_queuetime
(
self
):
def
test_recentmost_queuetime
(
self
):
'''
'''
Test whether the LoncapaProblem knows about the time of queue requests
Test whether the LoncapaProblem knows about the time of queue requests
'''
'''
problem_file
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
"test_files/coderesponse.xml"
)
answer_ids
=
sorted
(
self
.
problem
.
get_question_answers
())
with
open
(
problem_file
)
as
input_file
:
test_lcp
=
lcp
.
LoncapaProblem
(
input_file
.
read
(),
'1'
,
system
=
test_system
)
answer_ids
=
sorted
(
test_lcp
.
get_question_answers
())
# CodeResponse requires internal CorrectMap state. Build it now in the unqueued state
# CodeResponse requires internal CorrectMap state. Build it now in the unqueued state
cmap
=
CorrectMap
()
cmap
=
CorrectMap
()
for
answer_id
in
answer_ids
:
for
answer_id
in
answer_ids
:
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_id
,
queuestate
=
None
))
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_id
,
queuestate
=
None
))
test_lcp
.
correct_map
.
update
(
cmap
)
self
.
problem
.
correct_map
.
update
(
cmap
)
self
.
assertEquals
(
test_lcp
.
get_recentmost_queuetime
(),
None
)
self
.
assertEquals
(
self
.
problem
.
get_recentmost_queuetime
(),
None
)
# CodeResponse requires internal CorrectMap state. Build it now in the queued state
# CodeResponse requires internal CorrectMap state. Build it now in the queued state
cmap
=
CorrectMap
()
cmap
=
CorrectMap
()
...
@@ -519,18 +516,18 @@ class CodeResponseTest(unittest.TestCase):
...
@@ -519,18 +516,18 @@ class CodeResponseTest(unittest.TestCase):
latest_timestamp
=
datetime
.
now
()
latest_timestamp
=
datetime
.
now
()
queuestate
=
CodeResponseTest
.
make_queuestate
(
1000
+
i
,
latest_timestamp
)
queuestate
=
CodeResponseTest
.
make_queuestate
(
1000
+
i
,
latest_timestamp
)
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_id
,
queuestate
=
queuestate
))
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_id
,
queuestate
=
queuestate
))
test_lcp
.
correct_map
.
update
(
cmap
)
self
.
problem
.
correct_map
.
update
(
cmap
)
# Queue state only tracks up to second
# Queue state only tracks up to second
latest_timestamp
=
datetime
.
strptime
(
datetime
.
strftime
(
latest_timestamp
,
dateformat
),
dateformat
)
latest_timestamp
=
datetime
.
strptime
(
datetime
.
strftime
(
latest_timestamp
,
dateformat
),
dateformat
)
self
.
assertEquals
(
test_lcp
.
get_recentmost_queuetime
(),
latest_timestamp
)
self
.
assertEquals
(
self
.
problem
.
get_recentmost_queuetime
(),
latest_timestamp
)
def
test_convert_files_to_filenames
(
self
):
def
test_convert_files_to_filenames
(
self
):
'''
'''
Test whether file objects are converted to filenames without altering other structures
Test whether file objects are converted to filenames without altering other structures
'''
'''
problem_file
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
"test_files/coderesponse.xml
"
)
problem_file
=
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
"test_files/filename_convert_test.txt
"
)
with
open
(
problem_file
)
as
fp
:
with
open
(
problem_file
)
as
fp
:
answers_with_file
=
{
'1_2_1'
:
'String-based answer'
,
answers_with_file
=
{
'1_2_1'
:
'String-based answer'
,
'1_3_1'
:
[
'answer1'
,
'answer2'
,
'answer3'
],
'1_3_1'
:
[
'answer1'
,
'answer2'
,
'answer3'
],
...
@@ -540,7 +537,6 @@ class CodeResponseTest(unittest.TestCase):
...
@@ -540,7 +537,6 @@ class CodeResponseTest(unittest.TestCase):
self
.
assertEquals
(
answers_converted
[
'1_3_1'
],
[
'answer1'
,
'answer2'
,
'answer3'
])
self
.
assertEquals
(
answers_converted
[
'1_3_1'
],
[
'answer1'
,
'answer2'
,
'answer3'
])
self
.
assertEquals
(
answers_converted
[
'1_4_1'
],
[
fp
.
name
,
fp
.
name
])
self
.
assertEquals
(
answers_converted
[
'1_4_1'
],
[
fp
.
name
,
fp
.
name
])
class
ChoiceResponseTest
(
ResponseTest
):
class
ChoiceResponseTest
(
ResponseTest
):
from
response_xml_factory
import
ChoiceResponseXMLFactory
from
response_xml_factory
import
ChoiceResponseXMLFactory
xml_factory_class
=
ChoiceResponseXMLFactory
xml_factory_class
=
ChoiceResponseXMLFactory
...
...
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