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
f62dad2f
Commit
f62dad2f
authored
Mar 05, 2013
by
Will Daly
Committed by
Ned Batchelder
May 06, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added symbolic response tests
parent
e61a6fe7
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
155 additions
and
63 deletions
+155
-63
common/lib/capa/capa/inputtypes.py
+1
-1
common/lib/capa/capa/responsetypes.py
+16
-4
common/lib/capa/capa/tests/response_xml_factory.py
+35
-0
common/lib/capa/capa/tests/test_responsetypes.py
+102
-57
common/lib/capa/capa/util.py
+1
-1
No files found.
common/lib/capa/capa/inputtypes.py
View file @
f62dad2f
...
@@ -46,7 +46,7 @@ import sys
...
@@ -46,7 +46,7 @@ import sys
import
pyparsing
import
pyparsing
from
.registry
import
TagRegistry
from
.registry
import
TagRegistry
from
c
apa.c
hem
import
chemcalc
from
chem
import
chemcalc
import
xqueue_interface
import
xqueue_interface
from
datetime
import
datetime
from
datetime
import
datetime
...
...
common/lib/capa/capa/responsetypes.py
View file @
f62dad2f
...
@@ -29,7 +29,7 @@ from collections import namedtuple
...
@@ -29,7 +29,7 @@ from collections import namedtuple
from
shapely.geometry
import
Point
,
MultiPoint
from
shapely.geometry
import
Point
,
MultiPoint
# specific library imports
# specific library imports
from
.
calc
import
evaluator
,
UndefinedVariable
from
calc
import
evaluator
,
UndefinedVariable
from
.correctmap
import
CorrectMap
from
.correctmap
import
CorrectMap
from
datetime
import
datetime
from
datetime
import
datetime
from
.util
import
*
from
.util
import
*
...
@@ -1043,7 +1043,7 @@ class CustomResponse(LoncapaResponse):
...
@@ -1043,7 +1043,7 @@ class CustomResponse(LoncapaResponse):
messages
=
self
.
context
[
'messages'
]
messages
=
self
.
context
[
'messages'
]
correct_map
=
CorrectMap
()
correct_map
=
CorrectMap
()
overall_message
=
self
.
clean_message_html
(
self
.
context
[
'overall_message'
])
)
overall_message
=
self
.
clean_message_html
(
self
.
context
[
'overall_message'
])
correct_map
.
set_overall_message
(
overall_message
)
correct_map
.
set_overall_message
(
overall_message
)
for
k
in
range
(
len
(
idset
)):
for
k
in
range
(
len
(
idset
)):
...
@@ -1195,12 +1195,24 @@ class SymbolicResponse(CustomResponse):
...
@@ -1195,12 +1195,24 @@ class SymbolicResponse(CustomResponse):
"""
"""
response_tag
=
'symbolicresponse'
response_tag
=
'symbolicresponse'
max_inputfields
=
1
def
setup_response
(
self
):
# Symbolic response always uses symmath_check()
# If the XML did not specify this, then set it now
# Otherwise, we get an error from the superclass
self
.
xml
.
set
(
'cfn'
,
'symmath_check'
)
# Let CustomResponse do its setup
super
(
SymbolicResponse
,
self
)
.
setup_response
()
def
execute_check_function
(
self
,
idset
,
submission
):
def
execute_check_function
(
self
,
idset
,
submission
):
from
symmath
import
symmath_check
from
symmath
import
symmath_check
fn
=
self
.
code
try
:
try
:
answer_given
=
submission
[
0
]
if
(
len
(
idset
)
==
1
)
else
submission
# Since we have limited max_inputfields to 1,
# we can assume that there is only one submission
answer_given
=
submission
[
0
]
ret
=
symmath_check
(
ret
=
symmath_check
(
self
.
expect
,
answer_given
,
self
.
expect
,
answer_given
,
dynamath
=
self
.
context
.
get
(
'dynamath'
),
dynamath
=
self
.
context
.
get
(
'dynamath'
),
...
...
common/lib/capa/capa/tests/response_xml_factory.py
View file @
f62dad2f
...
@@ -734,3 +734,38 @@ class AnnotationResponseXMLFactory(ResponseXMLFactory):
...
@@ -734,3 +734,38 @@ class AnnotationResponseXMLFactory(ResponseXMLFactory):
option_element
.
text
=
description
option_element
.
text
=
description
return
input_element
return
input_element
class
SymbolicResponseXMLFactory
(
ResponseXMLFactory
):
""" Factory for producing <symbolicresponse> xml """
def
create_response_element
(
self
,
**
kwargs
):
""" Build the <symbolicresponse> XML element.
Uses **kwargs:
*expect*: The correct answer (a sympy string)
*options*: list of option strings to pass to symmath_check
(e.g. 'matrix', 'qbit', 'imaginary', 'numerical')"""
# Retrieve **kwargs
expect
=
kwargs
.
get
(
'expect'
,
''
)
options
=
kwargs
.
get
(
'options'
,
[])
# Symmath check expects a string of options
options_str
=
","
.
join
(
options
)
# Construct the <symbolicresponse> element
response_element
=
etree
.
Element
(
'symbolicresponse'
)
if
expect
:
response_element
.
set
(
'expect'
,
str
(
expect
))
if
options_str
:
response_element
.
set
(
'options'
,
str
(
options_str
))
return
response_element
def
create_input_element
(
self
,
**
kwargs
):
return
ResponseXMLFactory
.
textline_input_xml
(
**
kwargs
)
common/lib/capa/capa/tests/test_responsetypes.py
View file @
f62dad2f
...
@@ -10,6 +10,7 @@ import random
...
@@ -10,6 +10,7 @@ import random
import
unittest
import
unittest
import
textwrap
import
textwrap
import
mock
import
mock
import
textwrap
from
.
import
test_system
from
.
import
test_system
...
@@ -184,44 +185,85 @@ class ImageResponseTest(ResponseTest):
...
@@ -184,44 +185,85 @@ class ImageResponseTest(ResponseTest):
self
.
assert_answer_format
(
problem
)
self
.
assert_answer_format
(
problem
)
class
SymbolicResponseTest
(
unittest
.
TestCase
):
class
SymbolicResponseTest
(
ResponseTest
):
from
response_xml_factory
import
SymbolicResponseXMLFactory
from
response_xml_factory
import
SymbolicResponseXMLFactory
xml_factory_class
=
SymbolicResponseXMLFactory
xml_factory_class
=
SymbolicResponseXMLFactory
def
test_symbolic_response_grade
(
self
):
def
test_grade_single_input
(
self
):
symbolicresponse_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/symbolicresponse.xml"
problem
=
self
.
build_problem
(
math_display
=
True
,
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
symbolicresponse_file
)
.
read
(),
'1'
,
system
=
test_system
)
expect
=
"2*x+3*y"
)
correct_answers
=
{
'1_2_1'
:
'cos(theta)*[[1,0],[0,1]] + i*sin(theta)*[[0,1],[1,0]]'
,
'1_2_1_dynamath'
:
'''
# Correct answers
correct_inputs
=
[
(
'2x+3y'
,
textwrap
.
dedent
(
"""
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mstyle displaystyle="true">
<mn>2</mn><mo>*</mo><mi>x</mi><mo>+</mo><mn>3</mn><mo>*</mo><mi>y</mi>
</mstyle></math>"""
)),
(
'x+x+3y'
,
textwrap
.
dedent
(
"""
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mstyle displaystyle="true">
<mi>x</mi><mo>+</mo><mi>x</mi><mo>+</mo><mn>3</mn><mo>*</mo><mi>y</mi>
</mstyle></math>"""
)),
]
for
(
input_str
,
input_mathml
)
in
correct_inputs
:
self
.
_assert_symbolic_grade
(
problem
,
input_str
,
input_mathml
,
'correct'
)
# Incorrect answers
incorrect_inputs
=
[
(
'0'
,
''
),
(
'4x+3y'
,
textwrap
.
dedent
(
"""
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mstyle displaystyle="true">
<mn>4</mn><mo>*</mo><mi>x</mi><mo>+</mo><mn>3</mn><mo>*</mo><mi>y</mi>
</mstyle></math>"""
)),
]
for
(
input_str
,
input_mathml
)
in
incorrect_inputs
:
self
.
_assert_symbolic_grade
(
problem
,
input_str
,
input_mathml
,
'incorrect'
)
def
test_complex_number_grade
(
self
):
problem
=
self
.
build_problem
(
math_display
=
True
,
expect
=
"[[cos(theta),i*sin(theta)],[i*sin(theta),cos(theta)]]"
,
options
=
[
"matrix"
,
"imaginary"
])
# For LaTeX-style inputs, symmath_check() will try to contact
# a server to convert the input to MathML.
# We mock out the server, simulating the response that it would give
# for this input.
import
requests
dirpath
=
os
.
path
.
dirname
(
__file__
)
correct_snuggletex_response
=
open
(
os
.
path
.
join
(
dirpath
,
"test_files/snuggletex_correct.html"
))
.
read
()
.
decode
(
'utf8'
)
wrong_snuggletex_response
=
open
(
os
.
path
.
join
(
dirpath
,
"test_files/snuggletex_wrong.html"
))
.
read
()
.
decode
(
'utf8'
)
# Correct answer
with
mock
.
patch
.
object
(
requests
,
'post'
)
as
mock_post
:
# Simulate what the LaTeX-to-MathML server would
# send for the correct response input
mock_post
.
return_value
.
text
=
correct_snuggletex_response
self
.
_assert_symbolic_grade
(
problem
,
"cos(theta)*[[1,0],[0,1]] + i*sin(theta)*[[0,1],[1,0]]"
,
textwrap
.
dedent
(
"""
<math xmlns="http://www.w3.org/1998/Math/MathML">
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mstyle displaystyle="true">
<mstyle displaystyle="true">
<mrow>
<mrow>
<mi>cos</mi>
<mi>cos</mi>
<mrow>
<mrow><mo>(</mo><mi>θ</mi><mo>)</mo></mrow>
<mo>(</mo>
<mi>θ</mi>
<mo>)</mo>
</mrow>
</mrow>
</mrow>
<mo>⋅</mo>
<mo>⋅</mo>
<mrow>
<mrow>
<mo>[</mo>
<mo>[</mo>
<mtable>
<mtable>
<mtr>
<mtr>
<mtd>
<mtd><mn>1</mn></mtd><mtd><mn>0</mn></mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
</mtr>
</mtr>
<mtr>
<mtr>
<mtd>
<mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>1</mn>
</mtd>
</mtr>
</mtr>
</mtable>
</mtable>
<mo>]</mo>
<mo>]</mo>
...
@@ -232,9 +274,7 @@ class SymbolicResponseTest(unittest.TestCase):
...
@@ -232,9 +274,7 @@ class SymbolicResponseTest(unittest.TestCase):
<mrow>
<mrow>
<mi>sin</mi>
<mi>sin</mi>
<mrow>
<mrow>
<mo>(</mo>
<mo>(</mo><mi>θ</mi><mo>)</mo>
<mi>θ</mi>
<mo>)</mo>
</mrow>
</mrow>
</mrow>
</mrow>
<mo>⋅</mo>
<mo>⋅</mo>
...
@@ -242,49 +282,54 @@ class SymbolicResponseTest(unittest.TestCase):
...
@@ -242,49 +282,54 @@ class SymbolicResponseTest(unittest.TestCase):
<mo>[</mo>
<mo>[</mo>
<mtable>
<mtable>
<mtr>
<mtr>
<mtd>
<mtd><mn>0</mn></mtd><mtd><mn>1</mn></mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>1</mn>
</mtd>
</mtr>
</mtr>
<mtr>
<mtr>
<mtd>
<mtd><mn>1</mn></mtd><mtd><mn>0</mn></mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
</mtr>
</mtr>
</mtable>
</mtable>
<mo>]</mo>
<mo>]</mo>
</mrow>
</mrow>
</mstyle>
</mstyle>
</math>
</math>
'''
,
"""
),
}
'correct'
)
wrong_answers
=
{
'1_2_1'
:
'2'
,
'1_2_1_dynamath'
:
'''
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mstyle displaystyle="true">
<mn>2</mn>
</mstyle>
</math>'''
,
}
import
requests
d
=
os
.
path
.
dirname
(
__file__
)
correct_snuggletex_response
=
open
(
os
.
path
.
join
(
d
,
"test_files/snuggletex_correct.html"
))
.
read
()
.
decode
(
'utf8'
)
wrong_snuggletex_response
=
open
(
os
.
path
.
join
(
d
,
"test_files/snuggletex_wrong.html"
))
.
read
()
.
decode
(
'utf8'
)
# Incorrect answer
with
mock
.
patch
.
object
(
requests
,
'post'
)
as
mock_post
:
with
mock
.
patch
.
object
(
requests
,
'post'
)
as
mock_post
:
mock_post
.
return_value
.
text
=
correct_snuggletex_response
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
with
mock
.
patch
.
object
(
requests
,
'post'
)
as
mock_post
:
# Simulate what the LaTeX-to-MathML server would
# send for the incorrect response input
mock_post
.
return_value
.
text
=
wrong_snuggletex_response
mock_post
.
return_value
.
text
=
wrong_snuggletex_response
self
.
assertEquals
(
test_lcp
.
grade_answers
(
wrong_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
self
.
_assert_symbolic_grade
(
problem
,
"2"
,
textwrap
.
dedent
(
"""
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mstyle displaystyle="true"><mn>2</mn></mstyle>
</math>
"""
),
'incorrect'
)
def
test_multiple_inputs_exception
(
self
):
# Should not allow multiple inputs, since we specify
# only one "expect" value
with
self
.
assertRaises
(
Exception
):
problem
=
self
.
build_problem
(
math_display
=
True
,
expect
=
"2*x+3*y"
,
num_inputs
=
3
)
def
_assert_symbolic_grade
(
self
,
problem
,
student_input
,
dynamath_input
,
expected_correctness
):
input_dict
=
{
'1_2_1'
:
str
(
student_input
),
'1_2_1_dynamath'
:
str
(
dynamath_input
)
}
correct_map
=
problem
.
grade_answers
(
input_dict
)
self
.
assertEqual
(
correct_map
.
get_correctness
(
'1_2_1'
),
expected_correctness
)
class
OptionResponseTest
(
ResponseTest
):
class
OptionResponseTest
(
ResponseTest
):
...
...
common/lib/capa/capa/util.py
View file @
f62dad2f
from
.calc
import
evaluator
,
UndefinedVariable
from
calc
import
evaluator
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
#
#
...
...
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