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
c30f5702
Commit
c30f5702
authored
Oct 08, 2012
by
Victor Shnayder
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move more tests around, start prep for inputtype refactor
parent
66604fd0
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
409 additions
and
368 deletions
+409
-368
common/lib/capa/capa/inputtypes.py
+5
-3
common/lib/capa/capa/tests/__init__.py
+3
-1
common/lib/capa/capa/tests/test_inputtypes.py
+17
-364
common/lib/capa/capa/tests/test_responsetypes.py
+384
-0
No files found.
common/lib/capa/capa/inputtypes.py
View file @
c30f5702
...
...
@@ -124,8 +124,8 @@ def register_render_function(fn, names=None, cls=SimpleInput):
else
:
raise
NotImplementedError
def
wrapped
():
return
fn
def
wrapped
(
*
args
,
**
kwargs
):
return
fn
(
*
args
,
**
kwargs
)
return
wrapped
#-----------------------------------------------------------------------------
...
...
@@ -146,12 +146,14 @@ def optioninput(element, value, status, render_template, msg=''):
raise
Exception
(
"[courseware.capa.inputtypes.optioninput] Missing options specification in "
+
etree
.
tostring
(
element
))
# parse the set of possible options
oset
=
shlex
.
shlex
(
options
[
1
:
-
1
])
oset
.
quotes
=
"'"
oset
.
whitespace
=
","
oset
=
[
x
[
1
:
-
1
]
for
x
in
list
(
oset
)]
# make ordered list with (key,value) same
# make ordered list with (key,
value) same
osetdict
=
[(
oset
[
x
],
oset
[
x
])
for
x
in
range
(
len
(
oset
))]
# TODO: allow ordering to be randomized
...
...
common/lib/capa/capa/tests/__init__.py
View file @
c30f5702
...
...
@@ -4,6 +4,8 @@ import os
from
mock
import
Mock
TEST_DIR
=
os
.
path
.
dirname
(
os
.
path
.
realpath
(
__file__
))
test_system
=
Mock
(
ajax_url
=
'courses/course_id/modx/a_location'
,
track_function
=
Mock
(),
...
...
@@ -11,7 +13,7 @@ test_system = Mock(
render_template
=
Mock
(),
replace_urls
=
Mock
(),
user
=
Mock
(),
filestore
=
fs
.
osfs
.
OSFS
(
os
.
path
.
dirname
(
os
.
path
.
realpath
(
__file__
))
+
"/test_files"
),
filestore
=
fs
.
osfs
.
OSFS
(
os
.
path
.
join
(
TEST_DIR
,
"test_files"
)
),
debug
=
True
,
xqueue
=
{
'interface'
:
None
,
'callback_url'
:
'/'
,
'default_queuename'
:
'testqueue'
,
'waittime'
:
10
},
node_path
=
os
.
environ
.
get
(
"NODE_PATH"
,
"/usr/local/lib/node_modules"
),
...
...
common/lib/capa/capa/tests/test_inputtypes.py
View file @
c30f5702
...
...
@@ -10,375 +10,28 @@ import os
import
unittest
from
.
import
test_system
from
capa
import
inputtypes
import
capa.capa_problem
as
lcp
from
capa.correctmap
import
CorrectMap
from
capa.util
import
convert_files_to_filenames
from
capa.xqueue_interface
import
dateformat
from
lxml
import
etree
class
MultiChoiceTest
(
unittest
.
TestCase
):
def
test_MC_grade
(
self
):
multichoice_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/multichoice.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
multichoice_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'choice_foil3'
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
false_answers
=
{
'1_2_1'
:
'choice_foil2'
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
false_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
def
test_MC_bare_grades
(
self
):
multichoice_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/multi_bare.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
multichoice_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'choice_2'
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
false_answers
=
{
'1_2_1'
:
'choice_1'
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
false_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
def
test_TF_grade
(
self
):
truefalse_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/truefalse.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
truefalse_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
[
'choice_foil2'
,
'choice_foil1'
]}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
false_answers
=
{
'1_2_1'
:
[
'choice_foil1'
]}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
false_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
false_answers
=
{
'1_2_1'
:
[
'choice_foil1'
,
'choice_foil3'
]}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
false_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
false_answers
=
{
'1_2_1'
:
[
'choice_foil3'
]}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
false_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
false_answers
=
{
'1_2_1'
:
[
'choice_foil1'
,
'choice_foil2'
,
'choice_foil3'
]}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
false_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
class
ImageResponseTest
(
unittest
.
TestCase
):
def
test_ir_grade
(
self
):
imageresponse_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/imageresponse.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
imageresponse_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'(490,11)-(556,98)'
,
'1_2_2'
:
'(242,202)-(296,276)'
}
test_answers
=
{
'1_2_1'
:
'[500,20]'
,
'1_2_2'
:
'[250,300]'
,
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_2'
),
'incorrect'
)
class
SymbolicResponseTest
(
unittest
.
TestCase
):
def
test_sr_grade
(
self
):
raise
SkipTest
()
# This test fails due to dependencies on a local copy of snuggletex-webapp. Until we have figured that out, we'll just skip this test
symbolicresponse_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/symbolicresponse.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
symbolicresponse_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'cos(theta)*[[1,0],[0,1]] + i*sin(theta)*[[0,1],[1,0]]'
,
'1_2_1_dynamath'
:
'''
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mstyle displaystyle="true">
<mrow>
<mi>cos</mi>
<mrow>
<mo>(</mo>
<mi>θ</mi>
<mo>)</mo>
</mrow>
</mrow>
<mo>⋅</mo>
<mrow>
<mo>[</mo>
<mtable>
<mtr>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>1</mn>
</mtd>
</mtr>
</mtable>
<mo>]</mo>
</mrow>
<mo>+</mo>
<mi>i</mi>
<mo>⋅</mo>
<mrow>
<mi>sin</mi>
<mrow>
<mo>(</mo>
<mi>θ</mi>
<mo>)</mo>
</mrow>
</mrow>
<mo>⋅</mo>
<mrow>
<mo>[</mo>
<mtable>
<mtr>
<mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>1</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
</mtr>
</mtable>
<mo>]</mo>
</mrow>
</mstyle>
</math>
'''
,
}
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>'''
,
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
wrong_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
class
OptionResponseTest
(
unittest
.
TestCase
):
class
OptionInputTest
(
unittest
.
TestCase
):
'''
Run this with
python manage.py test courseware.OptionResponseTest
Make sure option inputs work
'''
def
test_or_grade
(
self
):
optionresponse_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/optionresponse.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
optionresponse_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'True'
,
'1_2_2'
:
'False'
}
test_answers
=
{
'1_2_1'
:
'True'
,
'1_2_2'
:
'True'
,
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_2'
),
'incorrect'
)
class
FormulaResponseWithHintTest
(
unittest
.
TestCase
):
'''
Test Formula response problem with a hint
This problem also uses calc.
'''
def
test_or_grade
(
self
):
problem_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/formularesponse_with_hint.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
problem_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'2.5*x-5.0'
}
test_answers
=
{
'1_2_1'
:
'0.4*x-5.0'
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
cmap
=
test_lcp
.
grade_answers
(
test_answers
)
self
.
assertEquals
(
cmap
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
self
.
assertTrue
(
'You have inverted'
in
cmap
.
get_hint
(
'1_2_1'
))
class
StringResponseWithHintTest
(
unittest
.
TestCase
):
'''
Test String response problem with a hint
'''
def
test_or_grade
(
self
):
problem_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/stringresponse_with_hint.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
problem_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'Michigan'
}
test_answers
=
{
'1_2_1'
:
'Minnesota'
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
cmap
=
test_lcp
.
grade_answers
(
test_answers
)
self
.
assertEquals
(
cmap
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
self
.
assertTrue
(
'St. Paul'
in
cmap
.
get_hint
(
'1_2_1'
))
class
CodeResponseTest
(
unittest
.
TestCase
):
'''
Test CodeResponse
TODO: Add tests for external grader messages
'''
@staticmethod
def
make_queuestate
(
key
,
time
):
timestr
=
datetime
.
strftime
(
time
,
dateformat
)
return
{
'key'
:
key
,
'time'
:
timestr
}
def
test_is_queued
(
self
):
"""
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
())
# CodeResponse requires internal CorrectMap state. Build it now in the unqueued state
cmap
=
CorrectMap
()
for
answer_id
in
answer_ids
:
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_id
,
queuestate
=
None
))
test_lcp
.
correct_map
.
update
(
cmap
)
self
.
assertEquals
(
test_lcp
.
is_queued
(),
False
)
# Now we queue the LCP
cmap
=
CorrectMap
()
for
i
,
answer_id
in
enumerate
(
answer_ids
):
queuestate
=
CodeResponseTest
.
make_queuestate
(
i
,
datetime
.
now
())
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_ids
[
i
],
queuestate
=
queuestate
))
test_lcp
.
correct_map
.
update
(
cmap
)
self
.
assertEquals
(
test_lcp
.
is_queued
(),
True
)
def
test_update_score
(
self
):
'''
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"
)
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
old_cmap
=
CorrectMap
()
for
i
,
answer_id
in
enumerate
(
answer_ids
):
queuekey
=
1000
+
i
queuestate
=
CodeResponseTest
.
make_queuestate
(
1000
+
i
,
datetime
.
now
())
old_cmap
.
update
(
CorrectMap
(
answer_id
=
answer_ids
[
i
],
queuestate
=
queuestate
))
# Message format common to external graders
grader_msg
=
'<span>MESSAGE</span>'
# Must be valid XML
correct_score_msg
=
json
.
dumps
({
'correct'
:
True
,
'score'
:
1
,
'msg'
:
grader_msg
})
incorrect_score_msg
=
json
.
dumps
({
'correct'
:
False
,
'score'
:
0
,
'msg'
:
grader_msg
})
xserver_msgs
=
{
'correct'
:
correct_score_msg
,
'incorrect'
:
incorrect_score_msg
,}
# Incorrect queuekey, state should not be updated
for
correctness
in
[
'correct'
,
'incorrect'
]:
test_lcp
.
correct_map
=
CorrectMap
()
test_lcp
.
correct_map
.
update
(
old_cmap
)
# Deep copy
test_lcp
.
update_score
(
xserver_msgs
[
correctness
],
queuekey
=
0
)
self
.
assertEquals
(
test_lcp
.
correct_map
.
get_dict
(),
old_cmap
.
get_dict
())
# Deep comparison
for
answer_id
in
answer_ids
:
self
.
assertTrue
(
test_lcp
.
correct_map
.
is_queued
(
answer_id
))
# Should be still queued, since message undelivered
# Correct queuekey, state should be updated
for
correctness
in
[
'correct'
,
'incorrect'
]:
for
i
,
answer_id
in
enumerate
(
answer_ids
):
test_lcp
.
correct_map
=
CorrectMap
()
test_lcp
.
correct_map
.
update
(
old_cmap
)
new_cmap
=
CorrectMap
()
new_cmap
.
update
(
old_cmap
)
npoints
=
1
if
correctness
==
'correct'
else
0
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
.
assertEquals
(
test_lcp
.
correct_map
.
get_dict
(),
new_cmap
.
get_dict
())
for
j
,
test_id
in
enumerate
(
answer_ids
):
if
j
==
i
:
self
.
assertFalse
(
test_lcp
.
correct_map
.
is_queued
(
test_id
))
# Should be dequeued, message delivered
else
:
self
.
assertTrue
(
test_lcp
.
correct_map
.
is_queued
(
test_id
))
# Should be queued, message undelivered
def
test_recentmost_queuetime
(
self
):
'''
Test whether the LoncapaProblem knows about the time of queue requests
'''
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
())
# CodeResponse requires internal CorrectMap state. Build it now in the unqueued state
cmap
=
CorrectMap
()
for
answer_id
in
answer_ids
:
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_id
,
queuestate
=
None
))
test_lcp
.
correct_map
.
update
(
cmap
)
self
.
assertEquals
(
test_lcp
.
get_recentmost_queuetime
(),
None
)
# CodeResponse requires internal CorrectMap state. Build it now in the queued state
cmap
=
CorrectMap
()
for
i
,
answer_id
in
enumerate
(
answer_ids
):
queuekey
=
1000
+
i
latest_timestamp
=
datetime
.
now
()
queuestate
=
CodeResponseTest
.
make_queuestate
(
1000
+
i
,
latest_timestamp
)
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_id
,
queuestate
=
queuestate
))
test_lcp
.
correct_map
.
update
(
cmap
)
# Queue state only tracks up to second
latest_timestamp
=
datetime
.
strptime
(
datetime
.
strftime
(
latest_timestamp
,
dateformat
),
dateformat
)
self
.
assertEquals
(
test_lcp
.
get_recentmost_queuetime
(),
latest_timestamp
)
def
test_convert_files_to_filenames
(
self
):
'''
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"
)
with
open
(
problem_file
)
as
fp
:
answers_with_file
=
{
'1_2_1'
:
'String-based answer'
,
'1_3_1'
:
[
'answer1'
,
'answer2'
,
'answer3'
],
'1_4_1'
:
[
fp
,
fp
]}
answers_converted
=
convert_files_to_filenames
(
answers_with_file
)
self
.
assertEquals
(
answers_converted
[
'1_2_1'
],
'String-based answer'
)
self
.
assertEquals
(
answers_converted
[
'1_3_1'
],
[
'answer1'
,
'answer2'
,
'answer3'
])
self
.
assertEquals
(
answers_converted
[
'1_4_1'
],
[
fp
.
name
,
fp
.
name
])
class
ChoiceResponseTest
(
unittest
.
TestCase
):
def
test_cr_rb_grade
(
self
):
problem_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/choiceresponse_radio.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
problem_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'choice_2'
,
'1_3_1'
:
[
'choice_2'
,
'choice_3'
]}
test_answers
=
{
'1_2_1'
:
'choice_2'
,
'1_3_1'
:
'choice_2'
,
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_3_1'
),
'incorrect'
)
def
test_cr_cb_grade
(
self
):
problem_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/choiceresponse_checkbox.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
problem_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'choice_2'
,
'1_3_1'
:
[
'choice_2'
,
'choice_3'
],
'1_4_1'
:
[
'choice_2'
,
'choice_3'
]}
test_answers
=
{
'1_2_1'
:
'choice_2'
,
'1_3_1'
:
'choice_2'
,
'1_4_1'
:
[
'choice_2'
,
'choice_3'
],
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_3_1'
),
'incorrect'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_4_1'
),
'correct'
)
def
test_rendering
(
self
):
xml
=
"""<optioninput options="('Up','Down')" id="sky_input" correct="Up"/>"""
element
=
etree
.
fromstring
(
xml
)
class
JavascriptResponseTest
(
unittest
.
TestCase
):
value
=
'Down'
status
=
'incorrect'
rendered_element
=
inputtypes
.
optioninput
(
element
,
value
,
status
,
test_system
.
render_template
)
rendered_str
=
etree
.
tostring
(
rendered_element
)
print
rendered_str
self
.
assertTrue
(
False
)
def
test_jr_grade
(
self
):
problem_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/javascriptresponse.xml"
coffee_file_path
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/js/*.coffee"
os
.
system
(
"coffee -c
%
s"
%
(
coffee_file_path
))
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
problem_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
json
.
dumps
({
0
:
4
})}
incorrect_answers
=
{
'1_2_1'
:
json
.
dumps
({
0
:
5
})}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
incorrect_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
# TODO: split each inputtype into a get_render_context function and a
# template property, and have the rendering done in one place. (and be
# able to test the logic without dealing with xml at least on the output
# end)
common/lib/capa/capa/tests/test_responsetypes.py
0 → 100644
View file @
c30f5702
"""
Tests of responsetypes
"""
from
datetime
import
datetime
import
json
from
nose.plugins.skip
import
SkipTest
import
os
import
unittest
from
.
import
test_system
import
capa.capa_problem
as
lcp
from
capa.correctmap
import
CorrectMap
from
capa.util
import
convert_files_to_filenames
from
capa.xqueue_interface
import
dateformat
class
MultiChoiceTest
(
unittest
.
TestCase
):
def
test_MC_grade
(
self
):
multichoice_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/multichoice.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
multichoice_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'choice_foil3'
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
false_answers
=
{
'1_2_1'
:
'choice_foil2'
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
false_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
def
test_MC_bare_grades
(
self
):
multichoice_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/multi_bare.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
multichoice_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'choice_2'
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
false_answers
=
{
'1_2_1'
:
'choice_1'
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
false_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
def
test_TF_grade
(
self
):
truefalse_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/truefalse.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
truefalse_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
[
'choice_foil2'
,
'choice_foil1'
]}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
false_answers
=
{
'1_2_1'
:
[
'choice_foil1'
]}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
false_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
false_answers
=
{
'1_2_1'
:
[
'choice_foil1'
,
'choice_foil3'
]}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
false_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
false_answers
=
{
'1_2_1'
:
[
'choice_foil3'
]}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
false_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
false_answers
=
{
'1_2_1'
:
[
'choice_foil1'
,
'choice_foil2'
,
'choice_foil3'
]}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
false_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
class
ImageResponseTest
(
unittest
.
TestCase
):
def
test_ir_grade
(
self
):
imageresponse_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/imageresponse.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
imageresponse_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'(490,11)-(556,98)'
,
'1_2_2'
:
'(242,202)-(296,276)'
}
test_answers
=
{
'1_2_1'
:
'[500,20]'
,
'1_2_2'
:
'[250,300]'
,
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_2'
),
'incorrect'
)
class
SymbolicResponseTest
(
unittest
.
TestCase
):
def
test_sr_grade
(
self
):
raise
SkipTest
()
# This test fails due to dependencies on a local copy of snuggletex-webapp. Until we have figured that out, we'll just skip this test
symbolicresponse_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/symbolicresponse.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
symbolicresponse_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'cos(theta)*[[1,0],[0,1]] + i*sin(theta)*[[0,1],[1,0]]'
,
'1_2_1_dynamath'
:
'''
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mstyle displaystyle="true">
<mrow>
<mi>cos</mi>
<mrow>
<mo>(</mo>
<mi>θ</mi>
<mo>)</mo>
</mrow>
</mrow>
<mo>⋅</mo>
<mrow>
<mo>[</mo>
<mtable>
<mtr>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>1</mn>
</mtd>
</mtr>
</mtable>
<mo>]</mo>
</mrow>
<mo>+</mo>
<mi>i</mi>
<mo>⋅</mo>
<mrow>
<mi>sin</mi>
<mrow>
<mo>(</mo>
<mi>θ</mi>
<mo>)</mo>
</mrow>
</mrow>
<mo>⋅</mo>
<mrow>
<mo>[</mo>
<mtable>
<mtr>
<mtd>
<mn>0</mn>
</mtd>
<mtd>
<mn>1</mn>
</mtd>
</mtr>
<mtr>
<mtd>
<mn>1</mn>
</mtd>
<mtd>
<mn>0</mn>
</mtd>
</mtr>
</mtable>
<mo>]</mo>
</mrow>
</mstyle>
</math>
'''
,
}
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>'''
,
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
wrong_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
class
OptionResponseTest
(
unittest
.
TestCase
):
'''
Run this with
python manage.py test courseware.OptionResponseTest
'''
def
test_or_grade
(
self
):
optionresponse_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/optionresponse.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
optionresponse_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'True'
,
'1_2_2'
:
'False'
}
test_answers
=
{
'1_2_1'
:
'True'
,
'1_2_2'
:
'True'
,
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_2'
),
'incorrect'
)
class
FormulaResponseWithHintTest
(
unittest
.
TestCase
):
'''
Test Formula response problem with a hint
This problem also uses calc.
'''
def
test_or_grade
(
self
):
problem_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/formularesponse_with_hint.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
problem_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'2.5*x-5.0'
}
test_answers
=
{
'1_2_1'
:
'0.4*x-5.0'
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
cmap
=
test_lcp
.
grade_answers
(
test_answers
)
self
.
assertEquals
(
cmap
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
self
.
assertTrue
(
'You have inverted'
in
cmap
.
get_hint
(
'1_2_1'
))
class
StringResponseWithHintTest
(
unittest
.
TestCase
):
'''
Test String response problem with a hint
'''
def
test_or_grade
(
self
):
problem_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/stringresponse_with_hint.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
problem_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'Michigan'
}
test_answers
=
{
'1_2_1'
:
'Minnesota'
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
cmap
=
test_lcp
.
grade_answers
(
test_answers
)
self
.
assertEquals
(
cmap
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
self
.
assertTrue
(
'St. Paul'
in
cmap
.
get_hint
(
'1_2_1'
))
class
CodeResponseTest
(
unittest
.
TestCase
):
'''
Test CodeResponse
TODO: Add tests for external grader messages
'''
@staticmethod
def
make_queuestate
(
key
,
time
):
timestr
=
datetime
.
strftime
(
time
,
dateformat
)
return
{
'key'
:
key
,
'time'
:
timestr
}
def
test_is_queued
(
self
):
"""
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
())
# CodeResponse requires internal CorrectMap state. Build it now in the unqueued state
cmap
=
CorrectMap
()
for
answer_id
in
answer_ids
:
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_id
,
queuestate
=
None
))
test_lcp
.
correct_map
.
update
(
cmap
)
self
.
assertEquals
(
test_lcp
.
is_queued
(),
False
)
# Now we queue the LCP
cmap
=
CorrectMap
()
for
i
,
answer_id
in
enumerate
(
answer_ids
):
queuestate
=
CodeResponseTest
.
make_queuestate
(
i
,
datetime
.
now
())
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_ids
[
i
],
queuestate
=
queuestate
))
test_lcp
.
correct_map
.
update
(
cmap
)
self
.
assertEquals
(
test_lcp
.
is_queued
(),
True
)
def
test_update_score
(
self
):
'''
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"
)
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
old_cmap
=
CorrectMap
()
for
i
,
answer_id
in
enumerate
(
answer_ids
):
queuekey
=
1000
+
i
queuestate
=
CodeResponseTest
.
make_queuestate
(
1000
+
i
,
datetime
.
now
())
old_cmap
.
update
(
CorrectMap
(
answer_id
=
answer_ids
[
i
],
queuestate
=
queuestate
))
# Message format common to external graders
grader_msg
=
'<span>MESSAGE</span>'
# Must be valid XML
correct_score_msg
=
json
.
dumps
({
'correct'
:
True
,
'score'
:
1
,
'msg'
:
grader_msg
})
incorrect_score_msg
=
json
.
dumps
({
'correct'
:
False
,
'score'
:
0
,
'msg'
:
grader_msg
})
xserver_msgs
=
{
'correct'
:
correct_score_msg
,
'incorrect'
:
incorrect_score_msg
,}
# Incorrect queuekey, state should not be updated
for
correctness
in
[
'correct'
,
'incorrect'
]:
test_lcp
.
correct_map
=
CorrectMap
()
test_lcp
.
correct_map
.
update
(
old_cmap
)
# Deep copy
test_lcp
.
update_score
(
xserver_msgs
[
correctness
],
queuekey
=
0
)
self
.
assertEquals
(
test_lcp
.
correct_map
.
get_dict
(),
old_cmap
.
get_dict
())
# Deep comparison
for
answer_id
in
answer_ids
:
self
.
assertTrue
(
test_lcp
.
correct_map
.
is_queued
(
answer_id
))
# Should be still queued, since message undelivered
# Correct queuekey, state should be updated
for
correctness
in
[
'correct'
,
'incorrect'
]:
for
i
,
answer_id
in
enumerate
(
answer_ids
):
test_lcp
.
correct_map
=
CorrectMap
()
test_lcp
.
correct_map
.
update
(
old_cmap
)
new_cmap
=
CorrectMap
()
new_cmap
.
update
(
old_cmap
)
npoints
=
1
if
correctness
==
'correct'
else
0
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
.
assertEquals
(
test_lcp
.
correct_map
.
get_dict
(),
new_cmap
.
get_dict
())
for
j
,
test_id
in
enumerate
(
answer_ids
):
if
j
==
i
:
self
.
assertFalse
(
test_lcp
.
correct_map
.
is_queued
(
test_id
))
# Should be dequeued, message delivered
else
:
self
.
assertTrue
(
test_lcp
.
correct_map
.
is_queued
(
test_id
))
# Should be queued, message undelivered
def
test_recentmost_queuetime
(
self
):
'''
Test whether the LoncapaProblem knows about the time of queue requests
'''
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
())
# CodeResponse requires internal CorrectMap state. Build it now in the unqueued state
cmap
=
CorrectMap
()
for
answer_id
in
answer_ids
:
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_id
,
queuestate
=
None
))
test_lcp
.
correct_map
.
update
(
cmap
)
self
.
assertEquals
(
test_lcp
.
get_recentmost_queuetime
(),
None
)
# CodeResponse requires internal CorrectMap state. Build it now in the queued state
cmap
=
CorrectMap
()
for
i
,
answer_id
in
enumerate
(
answer_ids
):
queuekey
=
1000
+
i
latest_timestamp
=
datetime
.
now
()
queuestate
=
CodeResponseTest
.
make_queuestate
(
1000
+
i
,
latest_timestamp
)
cmap
.
update
(
CorrectMap
(
answer_id
=
answer_id
,
queuestate
=
queuestate
))
test_lcp
.
correct_map
.
update
(
cmap
)
# Queue state only tracks up to second
latest_timestamp
=
datetime
.
strptime
(
datetime
.
strftime
(
latest_timestamp
,
dateformat
),
dateformat
)
self
.
assertEquals
(
test_lcp
.
get_recentmost_queuetime
(),
latest_timestamp
)
def
test_convert_files_to_filenames
(
self
):
'''
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"
)
with
open
(
problem_file
)
as
fp
:
answers_with_file
=
{
'1_2_1'
:
'String-based answer'
,
'1_3_1'
:
[
'answer1'
,
'answer2'
,
'answer3'
],
'1_4_1'
:
[
fp
,
fp
]}
answers_converted
=
convert_files_to_filenames
(
answers_with_file
)
self
.
assertEquals
(
answers_converted
[
'1_2_1'
],
'String-based answer'
)
self
.
assertEquals
(
answers_converted
[
'1_3_1'
],
[
'answer1'
,
'answer2'
,
'answer3'
])
self
.
assertEquals
(
answers_converted
[
'1_4_1'
],
[
fp
.
name
,
fp
.
name
])
class
ChoiceResponseTest
(
unittest
.
TestCase
):
def
test_cr_rb_grade
(
self
):
problem_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/choiceresponse_radio.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
problem_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'choice_2'
,
'1_3_1'
:
[
'choice_2'
,
'choice_3'
]}
test_answers
=
{
'1_2_1'
:
'choice_2'
,
'1_3_1'
:
'choice_2'
,
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_3_1'
),
'incorrect'
)
def
test_cr_cb_grade
(
self
):
problem_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/choiceresponse_checkbox.xml"
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
problem_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
'choice_2'
,
'1_3_1'
:
[
'choice_2'
,
'choice_3'
],
'1_4_1'
:
[
'choice_2'
,
'choice_3'
]}
test_answers
=
{
'1_2_1'
:
'choice_2'
,
'1_3_1'
:
'choice_2'
,
'1_4_1'
:
[
'choice_2'
,
'choice_3'
],
}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_3_1'
),
'incorrect'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
test_answers
)
.
get_correctness
(
'1_4_1'
),
'correct'
)
class
JavascriptResponseTest
(
unittest
.
TestCase
):
def
test_jr_grade
(
self
):
problem_file
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/javascriptresponse.xml"
coffee_file_path
=
os
.
path
.
dirname
(
__file__
)
+
"/test_files/js/*.coffee"
os
.
system
(
"coffee -c
%
s"
%
(
coffee_file_path
))
test_lcp
=
lcp
.
LoncapaProblem
(
open
(
problem_file
)
.
read
(),
'1'
,
system
=
test_system
)
correct_answers
=
{
'1_2_1'
:
json
.
dumps
({
0
:
4
})}
incorrect_answers
=
{
'1_2_1'
:
json
.
dumps
({
0
:
5
})}
self
.
assertEquals
(
test_lcp
.
grade_answers
(
incorrect_answers
)
.
get_correctness
(
'1_2_1'
),
'incorrect'
)
self
.
assertEquals
(
test_lcp
.
grade_answers
(
correct_answers
)
.
get_correctness
(
'1_2_1'
),
'correct'
)
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