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
f8adfc62
Commit
f8adfc62
authored
Mar 06, 2013
by
Diana Huang
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1602 from MITx/fix/will/capa_xmodule_unit_tests
Fix/will/capa xmodule unit tests
parents
cde4cdf8
c7d80a91
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
803 additions
and
99 deletions
+803
-99
common/lib/xmodule/xmodule/capa_module.py
+160
-60
common/lib/xmodule/xmodule/tests/__init__.py
+18
-4
common/lib/xmodule/xmodule/tests/test_capa_module.py
+587
-11
common/lib/xmodule/xmodule/tests/test_combined_open_ended.py
+24
-15
common/lib/xmodule/xmodule/tests/test_conditional.py
+6
-3
common/lib/xmodule/xmodule/tests/test_self_assessment.py
+8
-6
No files found.
common/lib/xmodule/xmodule/capa_module.py
View file @
f8adfc62
...
...
@@ -136,7 +136,7 @@ class CapaModule(XModule):
self
.
close_date
=
self
.
display_due_date
max_attempts
=
self
.
metadata
.
get
(
'attempts'
,
None
)
if
max_attempts
:
if
max_attempts
is
not
None
:
self
.
max_attempts
=
int
(
max_attempts
)
else
:
self
.
max_attempts
=
None
...
...
@@ -247,13 +247,87 @@ class CapaModule(XModule):
'progress'
:
Progress
.
to_js_status_str
(
self
.
get_progress
())
})
def
get_problem_html
(
self
,
encapsulate
=
True
):
'''Return html for the problem. Adds check, reset, save buttons
as necessary based on the problem config and state.'''
def
check_button_name
(
self
):
"""
Determine the name for the "check" button.
Usually it is just "Check", but if this is the student's
final attempt, change the name to "Final Check"
"""
if
self
.
max_attempts
is
not
None
:
final_check
=
(
self
.
attempts
>=
self
.
max_attempts
-
1
)
else
:
final_check
=
False
try
:
html
=
self
.
lcp
.
get_html
()
except
Exception
,
err
:
return
"Final Check"
if
final_check
else
"Check"
def
should_show_check_button
(
self
):
"""
Return True/False to indicate whether to show the "Check" button.
"""
submitted_without_reset
=
(
self
.
is_completed
()
and
self
.
rerandomize
==
"always"
)
# If the problem is closed (past due / too many attempts)
# then we do NOT show the "check" button
# Also, do not show the "check" button if we're waiting
# for the user to reset a randomized problem
if
self
.
closed
()
or
submitted_without_reset
:
return
False
else
:
return
True
def
should_show_reset_button
(
self
):
"""
Return True/False to indicate whether to show the "Reset" button.
"""
is_survey_question
=
(
self
.
max_attempts
==
0
)
if
self
.
rerandomize
in
[
"always"
,
"onreset"
]:
# If the problem is closed (and not a survey question with max_attempts==0),
# then do NOT show the reset button.
# If the problem hasn't been submitted yet, then do NOT show
# the reset button.
if
(
self
.
closed
()
and
not
is_survey_question
)
or
not
self
.
is_completed
():
return
False
else
:
return
True
# Only randomized problems need a "reset" button
else
:
return
False
def
should_show_save_button
(
self
):
"""
Return True/False to indicate whether to show the "Save" button.
"""
# If the user has forced the save button to display,
# then show it as long as the problem is not closed
# (past due / too many attempts)
if
self
.
force_save_button
==
"true"
:
return
not
self
.
closed
()
else
:
is_survey_question
=
(
self
.
max_attempts
==
0
)
needs_reset
=
self
.
is_completed
()
and
self
.
rerandomize
==
"always"
# If the problem is closed (and not a survey question with max_attempts==0),
# then do NOT show the reset button
# If we're waiting for the user to reset a randomized problem
# then do NOT show the reset button
if
(
self
.
closed
()
and
not
is_survey_question
)
or
needs_reset
:
return
False
else
:
return
True
def
handle_problem_html_error
(
self
,
err
):
"""
Change our problem to a dummy problem containing
a warning message to display to users.
Returns the HTML to show to users
*err* is the Exception encountered while rendering the problem HTML.
"""
log
.
exception
(
err
)
# TODO (vshnayder): another switch on DEBUG.
...
...
@@ -265,9 +339,10 @@ class CapaModule(XModule):
msg
+=
'<p>Error:</p><p><pre>
%
s</pre></p>'
%
str
(
err
)
.
replace
(
'<'
,
'<'
)
msg
+=
'<p><pre>
%
s</pre></p>'
%
traceback
.
format_exc
()
.
replace
(
'<'
,
'<'
)
html
=
msg
else
:
# We're in non-debug mode, and possibly even in production. We want
# to avoid bricking of problem as much as possible
else
:
# Presumably, student submission has corrupted LoncapaProblem HTML.
# First, pull down all student answers
...
...
@@ -308,62 +383,40 @@ class CapaModule(XModule):
log
.
exception
(
err
)
raise
content
=
{
'name'
:
self
.
display_name
,
'html'
:
html
,
'weight'
:
self
.
descriptor
.
weight
,
}
return
html
# We using strings as truthy values, because the terminology of the
# check button is context-specific.
# Put a "Check" button if unlimited attempts or still some left
if
self
.
max_attempts
is
None
or
self
.
attempts
<
self
.
max_attempts
-
1
:
check_button
=
"Check"
else
:
# Will be final check so let user know that
check_button
=
"Final Check"
def
get_problem_html
(
self
,
encapsulate
=
True
):
'''Return html for the problem. Adds check, reset, save buttons
as necessary based on the problem config and state.'''
reset_button
=
True
save_button
=
True
try
:
html
=
self
.
lcp
.
get_html
()
# If we're after deadline, or user has exhausted attempts,
# question is read-only.
if
self
.
closed
():
check_button
=
False
reset_button
=
False
save_button
=
False
# If we cannot construct the problem HTML,
# then generate an error message instead.
except
Exception
,
err
:
html
=
self
.
handle_problem_html_error
(
err
)
# If attempts=0 then show just check and reset buttons; this is for survey questions using capa
if
self
.
max_attempts
==
0
:
check_button
=
False
reset_button
=
True
save_button
=
True
# User submitted a problem, and hasn't reset. We don't want
# more submissions.
if
self
.
lcp
.
done
and
self
.
rerandomize
==
"always"
:
# The convention is to pass the name of the check button
# if we want to show a check button, and False otherwise
# This works because non-empty strings evaluate to True
if
self
.
should_show_check_button
():
check_button
=
self
.
check_button_name
()
else
:
check_button
=
False
save_button
=
False
# Only show the reset button if pressing it will show different values
if
self
.
rerandomize
not
in
[
"always"
,
"onreset"
]:
reset_button
=
False
# User hasn't submitted an answer yet -- we don't want resets
if
not
self
.
lcp
.
done
:
reset_button
=
False
# We may not need a "save" button if infinite number of attempts and
# non-randomized. The problem author can force it. It's a bit weird for
# randomization to control this; should perhaps be cleaned up.
if
(
self
.
force_save_button
==
"false"
)
and
(
self
.
max_attempts
is
None
and
self
.
rerandomize
!=
"always"
):
save_button
=
False
content
=
{
'name'
:
self
.
display_name
,
'html'
:
html
,
'weight'
:
self
.
descriptor
.
weight
,
}
context
=
{
'problem'
:
content
,
'id'
:
self
.
id
,
'check_button'
:
check_button
,
'reset_button'
:
reset_button
,
'save_button'
:
s
ave_button
,
'reset_button'
:
self
.
should_show_reset_button
()
,
'save_button'
:
s
elf
.
should_show_save_button
()
,
'answer_available'
:
self
.
answer_available
(),
'ajax_url'
:
self
.
system
.
ajax_url
,
'attempts_used'
:
self
.
attempts
,
...
...
@@ -419,7 +472,7 @@ class CapaModule(XModule):
def
closed
(
self
):
''' Is the student still allowed to submit answers? '''
if
self
.
attempts
=
=
self
.
max_attempts
:
if
self
.
max_attempts
is
not
None
and
self
.
attempts
>
=
self
.
max_attempts
:
return
True
if
self
.
is_past_due
():
return
True
...
...
@@ -528,21 +581,61 @@ class CapaModule(XModule):
def
make_dict_of_responses
(
get
):
'''Make dictionary of student responses (aka "answers")
get is POST dictionary.
The *get* dict has keys of the form 'x_y', which are mapped
to key 'y' in the returned dict. For example,
'input_1_2_3' would be mapped to '1_2_3' in the returned dict.
Some inputs always expect a list in the returned dict
(e.g. checkbox inputs). The convention is that
keys in the *get* dict that end with '[]' will always
have list values in the returned dict.
For example, if the *get* dict contains {'input_1[]': 'test' }
then the output dict would contain {'1': ['test'] }
(the value is a list).
Raises an exception if:
A key in the *get* dictionary does not contain >= 1 underscores
(e.g. "input" is invalid; "input_1" is valid)
Two keys end up with the same name in the returned dict.
(e.g. 'input_1' and 'input_1[]', which both get mapped
to 'input_1' in the returned dict)
'''
answers
=
dict
()
for
key
in
get
:
# e.g. input_resistor_1 ==> resistor_1
_
,
_
,
name
=
key
.
partition
(
'_'
)
# If key has no underscores, then partition
# will return (key, '', '')
# We detect this and raise an error
if
name
is
''
:
raise
ValueError
(
"
%
s must contain at least one underscore"
%
str
(
key
))
else
:
# This allows for answers which require more than one value for
# the same form input (e.g. checkbox inputs). The convention is that
# if the name ends with '[]' (which looks like an array), then the
# answer will be an array.
if
not
name
.
endswith
(
'[]'
):
answers
[
name
]
=
get
[
key
]
is_list_key
=
name
.
endswith
(
'[]'
)
name
=
name
[:
-
2
]
if
is_list_key
else
name
if
is_list_key
:
if
type
(
get
[
key
])
is
list
:
val
=
get
[
key
]
else
:
val
=
[
get
[
key
]]
else
:
name
=
name
[:
-
2
]
answers
[
name
]
=
get
.
getlist
(
key
)
val
=
get
[
key
]
# If the name already exists, then we don't want
# to override it. Raise an error instead
if
name
in
answers
:
raise
ValueError
(
"Key
%
s already exists in answers dict"
%
str
(
name
))
else
:
answers
[
name
]
=
val
return
answers
...
...
@@ -550,7 +643,7 @@ class CapaModule(XModule):
''' Checks whether answers to a problem are correct, and
returns a map of correct/incorrect answers:
{'success' :
bool
,
{'success' :
'correct' | 'incorrect' | AJAX alert msg string
,
'contents' : html}
'''
event_info
=
dict
()
...
...
@@ -663,7 +756,12 @@ class CapaModule(XModule):
''' Changes problem state to unfinished -- removes student answers,
and causes problem to rerender itself.
Returns problem html as { 'html' : html-string }.
Returns a dictionary of the form:
{'success': True/False,
'html': Problem HTML string }
If an error occurs, the dictionary will also have an
'error' key containing an error message.
'''
event_info
=
dict
()
event_info
[
'old_state'
]
=
self
.
lcp
.
get_state
()
...
...
@@ -687,6 +785,7 @@ class CapaModule(XModule):
# in next line)
self
.
lcp
.
seed
=
None
self
.
lcp
=
LoncapaProblem
(
self
.
definition
[
'data'
],
self
.
location
.
html_id
(),
self
.
lcp
.
get_state
(),
system
=
self
.
system
)
...
...
@@ -694,7 +793,8 @@ class CapaModule(XModule):
event_info
[
'new_state'
]
=
self
.
lcp
.
get_state
()
self
.
system
.
track_function
(
'reset_problem'
,
event_info
)
return
{
'html'
:
self
.
get_problem_html
(
encapsulate
=
False
)}
return
{
'success'
:
True
,
'html'
:
self
.
get_problem_html
(
encapsulate
=
False
)}
class
CapaDescriptor
(
RawDescriptor
):
...
...
common/lib/xmodule/xmodule/tests/__init__.py
View file @
f8adfc62
...
...
@@ -28,13 +28,27 @@ open_ended_grading_interface = {
'grading_controller'
:
'grading_controller'
}
test_system
=
ModuleSystem
(
def
test_system
():
"""
Construct a test ModuleSystem instance.
By default, the render_template() method simply returns
the context it is passed as a string.
You can override this behavior by monkey patching:
system = test_system()
system.render_template = my_render_func
where my_render_func is a function of the form
my_render_func(template, context)
"""
return
ModuleSystem
(
ajax_url
=
'courses/course_id/modx/a_location'
,
track_function
=
Mock
(),
get_module
=
Mock
(),
# "render" to just the context...
render_template
=
lambda
template
,
context
:
str
(
context
),
replace_urls
=
Mock
(
),
replace_urls
=
lambda
html
:
str
(
html
),
user
=
Mock
(
is_staff
=
False
),
filestore
=
Mock
(),
debug
=
True
,
...
...
@@ -42,7 +56,7 @@ test_system = ModuleSystem(
node_path
=
os
.
environ
.
get
(
"NODE_PATH"
,
"/usr/local/lib/node_modules"
),
anonymous_student_id
=
'student'
,
open_ended_grading_interface
=
open_ended_grading_interface
)
)
class
ModelsTest
(
unittest
.
TestCase
):
...
...
common/lib/xmodule/xmodule/tests/test_capa_module.py
View file @
f8adfc62
import
datetime
import
json
from
mock
import
Mock
from
mock
import
Mock
,
MagicMock
,
patch
from
pprint
import
pprint
import
unittest
import
random
import
xmodule
import
capa
from
xmodule.capa_module
import
CapaModule
from
xmodule.modulestore
import
Location
from
lxml
import
etree
...
...
@@ -34,6 +37,18 @@ class CapaFactory(object):
return
CapaFactory
.
num
@staticmethod
def
input_key
():
""" Return the input key to use when passing GET parameters """
return
(
"input_"
+
CapaFactory
.
answer_key
())
@staticmethod
def
answer_key
():
""" Return the key stored in the capa problem answer dict """
return
(
"-"
.
join
([
'i4x'
,
'edX'
,
'capa_test'
,
'problem'
,
'SampleProblem
%
d'
%
CapaFactory
.
num
])
+
"_2_1"
)
@staticmethod
def
create
(
graceperiod
=
None
,
due
=
None
,
max_attempts
=
None
,
...
...
@@ -59,11 +74,10 @@ class CapaFactory(object):
module.
attempts: also added to instance state. Will be converted to an int.
correct: if True, the problem will be initialized to be answered correctly.
"""
definition
=
{
'data'
:
CapaFactory
.
sample_problem_xml
,
}
location
=
Location
([
"i4x"
,
"edX"
,
"capa_test"
,
"problem"
,
"SampleProblem
{0}"
.
format
(
CapaFactory
.
next_num
()
)])
"SampleProblem
%
d"
%
CapaFactory
.
next_num
(
)])
metadata
=
{}
if
graceperiod
is
not
None
:
metadata
[
'graceperiod'
]
=
graceperiod
...
...
@@ -89,19 +103,12 @@ class CapaFactory(object):
# since everything else is a string.
instance_state_dict
[
'attempts'
]
=
int
(
attempts
)
if
correct
:
# TODO: make this actually set an answer of 3.14, and mark it correct
#instance_state_dict['student_answers'] = {}
#instance_state_dict['correct_map'] = {}
pass
if
len
(
instance_state_dict
)
>
0
:
instance_state
=
json
.
dumps
(
instance_state_dict
)
else
:
instance_state
=
None
module
=
CapaModule
(
test_system
,
location
,
module
=
CapaModule
(
test_system
()
,
location
,
definition
,
descriptor
,
instance_state
,
None
,
metadata
=
metadata
)
...
...
@@ -282,3 +289,572 @@ class CapaModuleTest(unittest.TestCase):
due
=
self
.
yesterday_str
,
graceperiod
=
self
.
two_day_delta_str
)
self
.
assertTrue
(
still_in_grace
.
answer_available
())
def
test_closed
(
self
):
# Attempts < Max attempts --> NOT closed
module
=
CapaFactory
.
create
(
max_attempts
=
"1"
,
attempts
=
"0"
)
self
.
assertFalse
(
module
.
closed
())
# Attempts < Max attempts --> NOT closed
module
=
CapaFactory
.
create
(
max_attempts
=
"2"
,
attempts
=
"1"
)
self
.
assertFalse
(
module
.
closed
())
# Attempts = Max attempts --> closed
module
=
CapaFactory
.
create
(
max_attempts
=
"1"
,
attempts
=
"1"
)
self
.
assertTrue
(
module
.
closed
())
# Attempts > Max attempts --> closed
module
=
CapaFactory
.
create
(
max_attempts
=
"1"
,
attempts
=
"2"
)
self
.
assertTrue
(
module
.
closed
())
# Max attempts = 0 --> closed
module
=
CapaFactory
.
create
(
max_attempts
=
"0"
,
attempts
=
"2"
)
self
.
assertTrue
(
module
.
closed
())
# Past due --> closed
module
=
CapaFactory
.
create
(
max_attempts
=
"1"
,
attempts
=
"0"
,
due
=
self
.
yesterday_str
)
self
.
assertTrue
(
module
.
closed
())
def
test_parse_get_params
(
self
):
# Valid GET param dict
valid_get_dict
=
{
'input_1'
:
'test'
,
'input_1_2'
:
'test'
,
'input_1_2_3'
:
'test'
,
'input_[]_3'
:
'test'
,
'input_4'
:
None
,
'input_5'
:
[],
'input_6'
:
5
}
result
=
CapaModule
.
make_dict_of_responses
(
valid_get_dict
)
# Expect that we get a dict with "input" stripped from key names
# and that we get the same values back
for
key
in
result
.
keys
():
original_key
=
"input_"
+
key
self
.
assertTrue
(
original_key
in
valid_get_dict
,
"Output dict should have key
%
s"
%
original_key
)
self
.
assertEqual
(
valid_get_dict
[
original_key
],
result
[
key
])
# Valid GET param dict with list keys
valid_get_dict
=
{
'input_2[]'
:
[
'test1'
,
'test2'
]}
result
=
CapaModule
.
make_dict_of_responses
(
valid_get_dict
)
self
.
assertTrue
(
'2'
in
result
)
self
.
assertEqual
(
valid_get_dict
[
'input_2[]'
],
result
[
'2'
])
# If we use [] at the end of a key name, we should always
# get a list, even if there's just one value
valid_get_dict
=
{
'input_1[]'
:
'test'
}
result
=
CapaModule
.
make_dict_of_responses
(
valid_get_dict
)
self
.
assertEqual
(
result
[
'1'
],
[
'test'
])
# If we have no underscores in the name, then the key is invalid
invalid_get_dict
=
{
'input'
:
'test'
}
with
self
.
assertRaises
(
ValueError
):
result
=
CapaModule
.
make_dict_of_responses
(
invalid_get_dict
)
# Two equivalent names (one list, one non-list)
# One of the values would overwrite the other, so detect this
# and raise an exception
invalid_get_dict
=
{
'input_1[]'
:
'test 1'
,
'input_1'
:
'test 2'
}
with
self
.
assertRaises
(
ValueError
):
result
=
CapaModule
.
make_dict_of_responses
(
invalid_get_dict
)
def
test_check_problem_correct
(
self
):
module
=
CapaFactory
.
create
(
attempts
=
1
)
# Simulate that all answers are marked correct, no matter
# what the input is, by patching CorrectMap.is_correct()
# Also simulate rendering the HTML
with
patch
(
'capa.correctmap.CorrectMap.is_correct'
)
as
mock_is_correct
,
\
patch
(
'xmodule.capa_module.CapaModule.get_problem_html'
)
as
mock_html
:
mock_is_correct
.
return_value
=
True
mock_html
.
return_value
=
"Test HTML"
# Check the problem
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
result
=
module
.
check_problem
(
get_request_dict
)
# Expect that the problem is marked correct
self
.
assertEqual
(
result
[
'success'
],
'correct'
)
# Expect that we get the (mocked) HTML
self
.
assertEqual
(
result
[
'contents'
],
'Test HTML'
)
# Expect that the number of attempts is incremented by 1
self
.
assertEqual
(
module
.
attempts
,
2
)
def
test_check_problem_incorrect
(
self
):
module
=
CapaFactory
.
create
(
attempts
=
0
)
# Simulate marking the input incorrect
with
patch
(
'capa.correctmap.CorrectMap.is_correct'
)
as
mock_is_correct
:
mock_is_correct
.
return_value
=
False
# Check the problem
get_request_dict
=
{
CapaFactory
.
input_key
():
'0'
}
result
=
module
.
check_problem
(
get_request_dict
)
# Expect that the problem is marked correct
self
.
assertEqual
(
result
[
'success'
],
'incorrect'
)
# Expect that the number of attempts is incremented by 1
self
.
assertEqual
(
module
.
attempts
,
1
)
def
test_check_problem_closed
(
self
):
module
=
CapaFactory
.
create
(
attempts
=
3
)
# Problem closed -- cannot submit
# Simulate that CapaModule.closed() always returns True
with
patch
(
'xmodule.capa_module.CapaModule.closed'
)
as
mock_closed
:
mock_closed
.
return_value
=
True
with
self
.
assertRaises
(
xmodule
.
exceptions
.
NotFoundError
):
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
module
.
check_problem
(
get_request_dict
)
# Expect that number of attempts NOT incremented
self
.
assertEqual
(
module
.
attempts
,
3
)
def
test_check_problem_resubmitted_with_randomize
(
self
):
# Randomize turned on
module
=
CapaFactory
.
create
(
rerandomize
=
'always'
,
attempts
=
0
)
# Simulate that the problem is completed
module
.
lcp
.
done
=
True
# Expect that we cannot submit
with
self
.
assertRaises
(
xmodule
.
exceptions
.
NotFoundError
):
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
module
.
check_problem
(
get_request_dict
)
# Expect that number of attempts NOT incremented
self
.
assertEqual
(
module
.
attempts
,
0
)
def
test_check_problem_resubmitted_no_randomize
(
self
):
# Randomize turned off
module
=
CapaFactory
.
create
(
rerandomize
=
'never'
,
attempts
=
0
)
# Simulate that the problem is completed
module
.
lcp
.
done
=
True
# Expect that we can submit successfully
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
result
=
module
.
check_problem
(
get_request_dict
)
self
.
assertEqual
(
result
[
'success'
],
'correct'
)
# Expect that number of attempts IS incremented
self
.
assertEqual
(
module
.
attempts
,
1
)
def
test_check_problem_queued
(
self
):
module
=
CapaFactory
.
create
(
attempts
=
1
)
# Simulate that the problem is queued
with
patch
(
'capa.capa_problem.LoncapaProblem.is_queued'
)
\
as
mock_is_queued
,
\
patch
(
'capa.capa_problem.LoncapaProblem.get_recentmost_queuetime'
)
\
as
mock_get_queuetime
:
mock_is_queued
.
return_value
=
True
mock_get_queuetime
.
return_value
=
datetime
.
datetime
.
now
()
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
result
=
module
.
check_problem
(
get_request_dict
)
# Expect an AJAX alert message in 'success'
self
.
assertTrue
(
'You must wait'
in
result
[
'success'
])
# Expect that the number of attempts is NOT incremented
self
.
assertEqual
(
module
.
attempts
,
1
)
def
test_check_problem_student_input_error
(
self
):
module
=
CapaFactory
.
create
(
attempts
=
1
)
# Simulate a student input exception
with
patch
(
'capa.capa_problem.LoncapaProblem.grade_answers'
)
as
mock_grade
:
mock_grade
.
side_effect
=
capa
.
responsetypes
.
StudentInputError
(
'test error'
)
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
result
=
module
.
check_problem
(
get_request_dict
)
# Expect an AJAX alert message in 'success'
self
.
assertTrue
(
'test error'
in
result
[
'success'
])
# Expect that the number of attempts is NOT incremented
self
.
assertEqual
(
module
.
attempts
,
1
)
def
test_reset_problem
(
self
):
module
=
CapaFactory
.
create
()
# Mock the module's capa problem
# to simulate that the problem is done
mock_problem
=
MagicMock
(
capa
.
capa_problem
.
LoncapaProblem
)
mock_problem
.
done
=
True
module
.
lcp
=
mock_problem
# Stub out HTML rendering
with
patch
(
'xmodule.capa_module.CapaModule.get_problem_html'
)
as
mock_html
:
mock_html
.
return_value
=
"<div>Test HTML</div>"
# Reset the problem
get_request_dict
=
{}
result
=
module
.
reset_problem
(
get_request_dict
)
# Expect that the request was successful
self
.
assertTrue
(
'success'
in
result
and
result
[
'success'
])
# Expect that the problem HTML is retrieved
self
.
assertTrue
(
'html'
in
result
)
self
.
assertEqual
(
result
[
'html'
],
"<div>Test HTML</div>"
)
# Expect that the problem was reset
mock_problem
.
do_reset
.
assert_called_once_with
()
def
test_reset_problem_closed
(
self
):
module
=
CapaFactory
.
create
()
# Simulate that the problem is closed
with
patch
(
'xmodule.capa_module.CapaModule.closed'
)
as
mock_closed
:
mock_closed
.
return_value
=
True
# Try to reset the problem
get_request_dict
=
{}
result
=
module
.
reset_problem
(
get_request_dict
)
# Expect that the problem was NOT reset
self
.
assertTrue
(
'success'
in
result
and
not
result
[
'success'
])
def
test_reset_problem_not_done
(
self
):
module
=
CapaFactory
.
create
()
# Simulate that the problem is NOT done
module
.
lcp
.
done
=
False
# Try to reset the problem
get_request_dict
=
{}
result
=
module
.
reset_problem
(
get_request_dict
)
# Expect that the problem was NOT reset
self
.
assertTrue
(
'success'
in
result
and
not
result
[
'success'
])
def
test_save_problem
(
self
):
module
=
CapaFactory
.
create
()
# Simulate that the problem is not done (not attempted or reset)
module
.
lcp
.
done
=
False
# Save the problem
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
result
=
module
.
save_problem
(
get_request_dict
)
# Expect that answers are saved to the problem
expected_answers
=
{
CapaFactory
.
answer_key
():
'3.14'
}
self
.
assertEqual
(
module
.
lcp
.
student_answers
,
expected_answers
)
# Expect that the result is success
self
.
assertTrue
(
'success'
in
result
and
result
[
'success'
])
def
test_save_problem_closed
(
self
):
module
=
CapaFactory
.
create
()
# Simulate that the problem is NOT done (not attempted or reset)
module
.
lcp
.
done
=
False
# Simulate that the problem is closed
with
patch
(
'xmodule.capa_module.CapaModule.closed'
)
as
mock_closed
:
mock_closed
.
return_value
=
True
# Try to save the problem
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
result
=
module
.
save_problem
(
get_request_dict
)
# Expect that the result is failure
self
.
assertTrue
(
'success'
in
result
and
not
result
[
'success'
])
def
test_save_problem_submitted_with_randomize
(
self
):
module
=
CapaFactory
.
create
(
rerandomize
=
'always'
)
# Simulate that the problem is completed
module
.
lcp
.
done
=
True
# Try to save
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
result
=
module
.
save_problem
(
get_request_dict
)
# Expect that we cannot save
self
.
assertTrue
(
'success'
in
result
and
not
result
[
'success'
])
def
test_save_problem_submitted_no_randomize
(
self
):
module
=
CapaFactory
.
create
(
rerandomize
=
'never'
)
# Simulate that the problem is completed
module
.
lcp
.
done
=
True
# Try to save
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
result
=
module
.
save_problem
(
get_request_dict
)
# Expect that we succeed
self
.
assertTrue
(
'success'
in
result
and
result
[
'success'
])
def
test_check_button_name
(
self
):
# If last attempt, button name changes to "Final Check"
# Just in case, we also check what happens if we have
# more attempts than allowed.
attempts
=
random
.
randint
(
1
,
10
)
module
=
CapaFactory
.
create
(
attempts
=
attempts
-
1
,
max_attempts
=
attempts
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Final Check"
)
module
=
CapaFactory
.
create
(
attempts
=
attempts
,
max_attempts
=
attempts
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Final Check"
)
module
=
CapaFactory
.
create
(
attempts
=
attempts
+
1
,
max_attempts
=
attempts
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Final Check"
)
# Otherwise, button name is "Check"
module
=
CapaFactory
.
create
(
attempts
=
attempts
-
2
,
max_attempts
=
attempts
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Check"
)
module
=
CapaFactory
.
create
(
attempts
=
attempts
-
3
,
max_attempts
=
attempts
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Check"
)
# If no limit on attempts, then always show "Check"
module
=
CapaFactory
.
create
(
attempts
=
attempts
-
3
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Check"
)
module
=
CapaFactory
.
create
(
attempts
=
0
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Check"
)
def
test_should_show_check_button
(
self
):
attempts
=
random
.
randint
(
1
,
10
)
# If we're after the deadline, do NOT show check button
module
=
CapaFactory
.
create
(
due
=
self
.
yesterday_str
)
self
.
assertFalse
(
module
.
should_show_check_button
())
# If user is out of attempts, do NOT show the check button
module
=
CapaFactory
.
create
(
attempts
=
attempts
,
max_attempts
=
attempts
)
self
.
assertFalse
(
module
.
should_show_check_button
())
# If survey question (max_attempts = 0), do NOT show the check button
module
=
CapaFactory
.
create
(
max_attempts
=
0
)
self
.
assertFalse
(
module
.
should_show_check_button
())
# If user submitted a problem but hasn't reset,
# do NOT show the check button
# Note: we can only reset when rerandomize="always"
module
=
CapaFactory
.
create
(
rerandomize
=
"always"
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_check_button
())
# Otherwise, DO show the check button
module
=
CapaFactory
.
create
()
self
.
assertTrue
(
module
.
should_show_check_button
())
# If the user has submitted the problem
# and we do NOT have a reset button, then we can show the check button
# Setting rerandomize to "never" ensures that the reset button
# is not shown
module
=
CapaFactory
.
create
(
rerandomize
=
"never"
)
module
.
lcp
.
done
=
True
self
.
assertTrue
(
module
.
should_show_check_button
())
def
test_should_show_reset_button
(
self
):
attempts
=
random
.
randint
(
1
,
10
)
# If we're after the deadline, do NOT show the reset button
module
=
CapaFactory
.
create
(
due
=
self
.
yesterday_str
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_reset_button
())
# If the user is out of attempts, do NOT show the reset button
module
=
CapaFactory
.
create
(
attempts
=
attempts
,
max_attempts
=
attempts
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_reset_button
())
# If we're NOT randomizing, then do NOT show the reset button
module
=
CapaFactory
.
create
(
rerandomize
=
"never"
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_reset_button
())
# If the user hasn't submitted an answer yet,
# then do NOT show the reset button
module
=
CapaFactory
.
create
()
module
.
lcp
.
done
=
False
self
.
assertFalse
(
module
.
should_show_reset_button
())
# Otherwise, DO show the reset button
module
=
CapaFactory
.
create
()
module
.
lcp
.
done
=
True
self
.
assertTrue
(
module
.
should_show_reset_button
())
# If survey question for capa (max_attempts = 0),
# DO show the reset button
module
=
CapaFactory
.
create
(
max_attempts
=
0
)
module
.
lcp
.
done
=
True
self
.
assertTrue
(
module
.
should_show_reset_button
())
def
test_should_show_save_button
(
self
):
attempts
=
random
.
randint
(
1
,
10
)
# If we're after the deadline, do NOT show the save button
module
=
CapaFactory
.
create
(
due
=
self
.
yesterday_str
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_save_button
())
# If the user is out of attempts, do NOT show the save button
module
=
CapaFactory
.
create
(
attempts
=
attempts
,
max_attempts
=
attempts
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_save_button
())
# If user submitted a problem but hasn't reset, do NOT show the save button
module
=
CapaFactory
.
create
(
rerandomize
=
"always"
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_save_button
())
# Otherwise, DO show the save button
module
=
CapaFactory
.
create
()
module
.
lcp
.
done
=
False
self
.
assertTrue
(
module
.
should_show_save_button
())
# If we're not randomizing, then we can re-save
module
=
CapaFactory
.
create
(
rerandomize
=
"never"
)
module
.
lcp
.
done
=
True
self
.
assertTrue
(
module
.
should_show_save_button
())
# If survey question for capa (max_attempts = 0),
# DO show the save button
module
=
CapaFactory
.
create
(
max_attempts
=
0
)
module
.
lcp
.
done
=
False
self
.
assertTrue
(
module
.
should_show_save_button
())
def
test_should_show_save_button_force_save_button
(
self
):
# If we're after the deadline, do NOT show the save button
# even though we're forcing a save
module
=
CapaFactory
.
create
(
due
=
self
.
yesterday_str
,
force_save_button
=
"true"
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_save_button
())
# If the user is out of attempts, do NOT show the save button
attempts
=
random
.
randint
(
1
,
10
)
module
=
CapaFactory
.
create
(
attempts
=
attempts
,
max_attempts
=
attempts
,
force_save_button
=
"true"
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_save_button
())
# Otherwise, if we force the save button,
# then show it even if we would ordinarily
# require a reset first
module
=
CapaFactory
.
create
(
force_save_button
=
"true"
,
rerandomize
=
"always"
)
module
.
lcp
.
done
=
True
self
.
assertTrue
(
module
.
should_show_save_button
())
def
test_get_problem_html
(
self
):
module
=
CapaFactory
.
create
()
# We've tested the show/hide button logic in other tests,
# so here we hard-wire the values
show_check_button
=
bool
(
random
.
randint
(
0
,
1
)
%
2
)
show_reset_button
=
bool
(
random
.
randint
(
0
,
1
)
%
2
)
show_save_button
=
bool
(
random
.
randint
(
0
,
1
)
%
2
)
module
.
should_show_check_button
=
Mock
(
return_value
=
show_check_button
)
module
.
should_show_reset_button
=
Mock
(
return_value
=
show_reset_button
)
module
.
should_show_save_button
=
Mock
(
return_value
=
show_save_button
)
# Mock the system rendering function
module
.
system
.
render_template
=
Mock
(
return_value
=
"<div>Test Template HTML</div>"
)
# Patch the capa problem's HTML rendering
with
patch
(
'capa.capa_problem.LoncapaProblem.get_html'
)
as
mock_html
:
mock_html
.
return_value
=
"<div>Test Problem HTML</div>"
# Render the problem HTML
html
=
module
.
get_problem_html
(
encapsulate
=
False
)
# Also render the problem encapsulated in a <div>
html_encapsulated
=
module
.
get_problem_html
(
encapsulate
=
True
)
# Expect that we get the rendered template back
self
.
assertEqual
(
html
,
"<div>Test Template HTML</div>"
)
# Check the rendering context
render_args
,
_
=
module
.
system
.
render_template
.
call_args
self
.
assertEqual
(
len
(
render_args
),
2
)
template_name
=
render_args
[
0
]
self
.
assertEqual
(
template_name
,
"problem.html"
)
context
=
render_args
[
1
]
self
.
assertEqual
(
context
[
'problem'
][
'html'
],
"<div>Test Problem HTML</div>"
)
self
.
assertEqual
(
bool
(
context
[
'check_button'
]),
show_check_button
)
self
.
assertEqual
(
bool
(
context
[
'reset_button'
]),
show_reset_button
)
self
.
assertEqual
(
bool
(
context
[
'save_button'
]),
show_save_button
)
# Assert that the encapsulated html contains the original html
self
.
assertTrue
(
html
in
html_encapsulated
)
def
test_get_problem_html_error
(
self
):
"""
In production, when an error occurs with the problem HTML
rendering, a "dummy" problem is created with an error
message to display to the user.
"""
module
=
CapaFactory
.
create
()
# Save the original problem so we can compare it later
original_problem
=
module
.
lcp
# Simulate throwing an exception when the capa problem
# is asked to render itself as HTML
module
.
lcp
.
get_html
=
Mock
(
side_effect
=
Exception
(
"Test"
))
# Stub out the test_system rendering function
module
.
system
.
render_template
=
Mock
(
return_value
=
"<div>Test Template HTML</div>"
)
# Turn off DEBUG
module
.
system
.
DEBUG
=
False
# Try to render the module with DEBUG turned off
html
=
module
.
get_problem_html
()
# Check the rendering context
render_args
,
_
=
module
.
system
.
render_template
.
call_args
context
=
render_args
[
1
]
self
.
assertTrue
(
"error"
in
context
[
'problem'
][
'html'
])
# Expect that the module has created a new dummy problem with the error
self
.
assertNotEqual
(
original_problem
,
module
.
lcp
)
common/lib/xmodule/xmodule/tests/test_combined_open_ended.py
View file @
f8adfc62
...
...
@@ -54,7 +54,8 @@ class OpenEndedChildTest(unittest.TestCase):
descriptor
=
Mock
()
def
setUp
(
self
):
self
.
openendedchild
=
OpenEndedChild
(
test_system
,
self
.
location
,
self
.
test_system
=
test_system
()
self
.
openendedchild
=
OpenEndedChild
(
self
.
test_system
,
self
.
location
,
self
.
definition
,
self
.
descriptor
,
self
.
static_data
,
self
.
metadata
)
...
...
@@ -69,7 +70,7 @@ class OpenEndedChildTest(unittest.TestCase):
def
test_latest_post_assessment_empty
(
self
):
answer
=
self
.
openendedchild
.
latest_post_assessment
(
test_system
)
answer
=
self
.
openendedchild
.
latest_post_assessment
(
self
.
test_system
)
self
.
assertEqual
(
answer
,
""
)
...
...
@@ -106,7 +107,7 @@ class OpenEndedChildTest(unittest.TestCase):
post_assessment
=
"Post assessment"
self
.
openendedchild
.
record_latest_post_assessment
(
post_assessment
)
self
.
assertEqual
(
post_assessment
,
self
.
openendedchild
.
latest_post_assessment
(
test_system
))
self
.
openendedchild
.
latest_post_assessment
(
self
.
test_system
))
def
test_get_score
(
self
):
new_answer
=
"New Answer"
...
...
@@ -125,7 +126,7 @@ class OpenEndedChildTest(unittest.TestCase):
def
test_reset
(
self
):
self
.
openendedchild
.
reset
(
test_system
)
self
.
openendedchild
.
reset
(
self
.
test_system
)
state
=
json
.
loads
(
self
.
openendedchild
.
get_instance_state
())
self
.
assertEqual
(
state
[
'state'
],
OpenEndedChild
.
INITIAL
)
...
...
@@ -182,11 +183,13 @@ class OpenEndedModuleTest(unittest.TestCase):
descriptor
=
Mock
()
def
setUp
(
self
):
test_system
.
location
=
self
.
location
self
.
test_system
=
test_system
()
self
.
test_system
.
location
=
self
.
location
self
.
mock_xqueue
=
MagicMock
()
self
.
mock_xqueue
.
send_to_queue
.
return_value
=
(
None
,
"Message"
)
test_system
.
xqueue
=
{
'interface'
:
self
.
mock_xqueue
,
'callback_url'
:
'/'
,
'default_queuename'
:
'testqueue'
,
'waittime'
:
1
}
self
.
openendedmodule
=
OpenEndedModule
(
test_system
,
self
.
location
,
self
.
test_system
.
xqueue
=
{
'interface'
:
self
.
mock_xqueue
,
'callback_url'
:
'/'
,
'default_queuename'
:
'testqueue'
,
'waittime'
:
1
}
self
.
openendedmodule
=
OpenEndedModule
(
self
.
test_system
,
self
.
location
,
self
.
definition
,
self
.
descriptor
,
self
.
static_data
,
self
.
metadata
)
def
test_message_post
(
self
):
...
...
@@ -195,7 +198,7 @@ class OpenEndedModuleTest(unittest.TestCase):
'grader_id'
:
'1'
,
'score'
:
3
}
qtime
=
datetime
.
strftime
(
datetime
.
now
(),
xqueue_interface
.
dateformat
)
student_info
=
{
'anonymous_student_id'
:
test_system
.
anonymous_student_id
,
student_info
=
{
'anonymous_student_id'
:
self
.
test_system
.
anonymous_student_id
,
'submission_time'
:
qtime
}
contents
=
{
'feedback'
:
get
[
'feedback'
],
...
...
@@ -205,7 +208,7 @@ class OpenEndedModuleTest(unittest.TestCase):
'student_info'
:
json
.
dumps
(
student_info
)
}
result
=
self
.
openendedmodule
.
message_post
(
get
,
test_system
)
result
=
self
.
openendedmodule
.
message_post
(
get
,
self
.
test_system
)
self
.
assertTrue
(
result
[
'success'
])
# make sure it's actually sending something we want to the queue
self
.
mock_xqueue
.
send_to_queue
.
assert_called_with
(
body
=
json
.
dumps
(
contents
),
header
=
ANY
)
...
...
@@ -216,7 +219,7 @@ class OpenEndedModuleTest(unittest.TestCase):
def
test_send_to_grader
(
self
):
submission
=
"This is a student submission"
qtime
=
datetime
.
strftime
(
datetime
.
now
(),
xqueue_interface
.
dateformat
)
student_info
=
{
'anonymous_student_id'
:
test_system
.
anonymous_student_id
,
student_info
=
{
'anonymous_student_id'
:
self
.
test_system
.
anonymous_student_id
,
'submission_time'
:
qtime
}
contents
=
self
.
openendedmodule
.
payload
.
copy
()
contents
.
update
({
...
...
@@ -224,7 +227,7 @@ class OpenEndedModuleTest(unittest.TestCase):
'student_response'
:
submission
,
'max_score'
:
self
.
max_score
})
result
=
self
.
openendedmodule
.
send_to_grader
(
submission
,
test_system
)
result
=
self
.
openendedmodule
.
send_to_grader
(
submission
,
self
.
test_system
)
self
.
assertTrue
(
result
)
self
.
mock_xqueue
.
send_to_queue
.
assert_called_with
(
body
=
json
.
dumps
(
contents
),
header
=
ANY
)
...
...
@@ -238,7 +241,7 @@ class OpenEndedModuleTest(unittest.TestCase):
}
get
=
{
'queuekey'
:
"abcd"
,
'xqueue_body'
:
score_msg
}
self
.
openendedmodule
.
update_score
(
get
,
test_system
)
self
.
openendedmodule
.
update_score
(
get
,
self
.
test_system
)
def
update_score_single
(
self
):
self
.
openendedmodule
.
new_history_entry
(
"New Entry"
)
...
...
@@ -261,11 +264,11 @@ class OpenEndedModuleTest(unittest.TestCase):
}
get
=
{
'queuekey'
:
"abcd"
,
'xqueue_body'
:
json
.
dumps
(
score_msg
)}
self
.
openendedmodule
.
update_score
(
get
,
test_system
)
self
.
openendedmodule
.
update_score
(
get
,
self
.
test_system
)
def
test_latest_post_assessment
(
self
):
self
.
update_score_single
()
assessment
=
self
.
openendedmodule
.
latest_post_assessment
(
test_system
)
assessment
=
self
.
openendedmodule
.
latest_post_assessment
(
self
.
test_system
)
self
.
assertFalse
(
assessment
==
''
)
# check for errors
self
.
assertFalse
(
'errors'
in
assessment
)
...
...
@@ -336,7 +339,13 @@ class CombinedOpenEndedModuleTest(unittest.TestCase):
descriptor
=
Mock
()
def
setUp
(
self
):
self
.
combinedoe
=
CombinedOpenEndedV1Module
(
test_system
,
self
.
location
,
self
.
definition
,
self
.
descriptor
,
static_data
=
self
.
static_data
,
metadata
=
self
.
metadata
)
self
.
test_system
=
test_system
()
self
.
combinedoe
=
CombinedOpenEndedV1Module
(
self
.
test_system
,
self
.
location
,
self
.
definition
,
self
.
descriptor
,
static_data
=
self
.
static_data
,
metadata
=
self
.
metadata
)
def
test_get_tag_name
(
self
):
name
=
self
.
combinedoe
.
get_tag_name
(
"<t>Tag</t>"
)
...
...
common/lib/xmodule/xmodule/tests/test_conditional.py
View file @
f8adfc62
...
...
@@ -56,6 +56,9 @@ class ConditionalModuleTest(unittest.TestCase):
'''Get a dummy system'''
return
DummySystem
(
load_error_modules
)
def
setUp
(
self
):
self
.
test_system
=
test_system
()
def
get_course
(
self
,
name
):
"""Get a test course by directory name. If there's more than one, error."""
print
"Importing {0}"
.
format
(
name
)
...
...
@@ -85,14 +88,14 @@ class ConditionalModuleTest(unittest.TestCase):
location
=
descriptor
.
location
instance_state
=
instance_states
.
get
(
location
.
category
,
None
)
print
"inner_get_module, location=
%
s, inst_state=
%
s"
%
(
location
,
instance_state
)
return
descriptor
.
xmodule_constructor
(
test_system
)(
instance_state
,
shared_state
)
return
descriptor
.
xmodule_constructor
(
self
.
test_system
)(
instance_state
,
shared_state
)
location
=
Location
([
"i4x"
,
"edX"
,
"cond_test"
,
"conditional"
,
"condone"
])
def
replace_urls
(
text
,
staticfiles_prefix
=
None
,
replace_prefix
=
'/static/'
,
course_namespace
=
None
):
return
text
test_system
.
replace_urls
=
replace_urls
test_system
.
get_module
=
inner_get_module
self
.
test_system
.
replace_urls
=
replace_urls
self
.
test_system
.
get_module
=
inner_get_module
module
=
inner_get_module
(
location
)
print
"module: "
,
module
...
...
common/lib/xmodule/xmodule/tests/test_self_assessment.py
View file @
f8adfc62
...
...
@@ -53,13 +53,13 @@ class SelfAssessmentTest(unittest.TestCase):
'skip_basic_checks'
:
False
,
}
self
.
module
=
SelfAssessmentModule
(
test_system
,
self
.
location
,
self
.
module
=
SelfAssessmentModule
(
test_system
()
,
self
.
location
,
self
.
definition
,
self
.
descriptor
,
static_data
,
state
,
metadata
=
self
.
metadata
)
def
test_get_html
(
self
):
html
=
self
.
module
.
get_html
(
test_
system
)
html
=
self
.
module
.
get_html
(
self
.
module
.
system
)
self
.
assertTrue
(
"This is sample prompt text"
in
html
)
def
test_self_assessment_flow
(
self
):
...
...
@@ -82,10 +82,11 @@ class SelfAssessmentTest(unittest.TestCase):
self
.
assertEqual
(
self
.
module
.
get_score
()[
'score'
],
0
)
self
.
module
.
save_answer
({
'student_answer'
:
"I am an answer"
},
test_system
)
self
.
module
.
save_answer
({
'student_answer'
:
"I am an answer"
},
self
.
module
.
system
)
self
.
assertEqual
(
self
.
module
.
state
,
self
.
module
.
ASSESSING
)
self
.
module
.
save_assessment
(
mock_query_dict
,
test_
system
)
self
.
module
.
save_assessment
(
mock_query_dict
,
self
.
module
.
system
)
self
.
assertEqual
(
self
.
module
.
state
,
self
.
module
.
DONE
)
...
...
@@ -94,7 +95,8 @@ class SelfAssessmentTest(unittest.TestCase):
self
.
assertEqual
(
self
.
module
.
state
,
self
.
module
.
INITIAL
)
# if we now assess as right, skip the REQUEST_HINT state
self
.
module
.
save_answer
({
'student_answer'
:
'answer 4'
},
test_system
)
self
.
module
.
save_answer
({
'student_answer'
:
'answer 4'
},
self
.
module
.
system
)
responses
[
'assessment'
]
=
'1'
self
.
module
.
save_assessment
(
mock_query_dict
,
test_
system
)
self
.
module
.
save_assessment
(
mock_query_dict
,
self
.
module
.
system
)
self
.
assertEqual
(
self
.
module
.
state
,
self
.
module
.
DONE
)
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