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
e5e0dc4b
Commit
e5e0dc4b
authored
Apr 17, 2013
by
Will Daly
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1865 from MITx/feature/will/more_capa_tests
Feature/will/more capa tests
parents
a3233b67
52c2f3ae
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
378 additions
and
23 deletions
+378
-23
common/lib/capa/capa/tests/test_input_templates.py
+269
-0
common/lib/xmodule/xmodule/tests/test_capa_module.py
+79
-22
lms/djangoapps/courseware/features/problems.feature
+5
-0
lms/djangoapps/courseware/features/problems.py
+25
-1
No files found.
common/lib/capa/capa/tests/test_input_templates.py
0 → 100644
View file @
e5e0dc4b
"""Tests for the logic in input type mako templates."""
import
unittest
import
capa
import
os.path
from
lxml
import
etree
from
mako.template
import
Template
as
MakoTemplate
class
TemplateTestCase
(
unittest
.
TestCase
):
"""Utilitites for testing templates"""
# Subclasses override this to specify the file name of the template
# to be loaded from capa/templates.
# The template name should include the .html extension:
# for example: choicegroup.html
TEMPLATE_NAME
=
None
def
setUp
(
self
):
"""Load the template"""
capa_path
=
capa
.
__path__
[
0
]
self
.
template_path
=
os
.
path
.
join
(
capa_path
,
'templates'
,
self
.
TEMPLATE_NAME
)
template_file
=
open
(
self
.
template_path
)
self
.
template
=
MakoTemplate
(
template_file
.
read
())
template_file
.
close
()
def
render_to_xml
(
self
,
context_dict
):
"""Render the template using the `context_dict` dict.
Returns an `etree` XML element."""
xml_str
=
self
.
template
.
render_unicode
(
**
context_dict
)
return
etree
.
fromstring
(
xml_str
)
def
assert_has_xpath
(
self
,
xml_root
,
xpath
,
context_dict
,
exact_num
=
1
):
"""Asserts that the xml tree has an element satisfying `xpath`.
`xml_root` is an etree XML element
`xpath` is an XPath string, such as `'/foo/bar'`
`context` is used to print a debugging message
`exact_num` is the exact number of matches to expect.
"""
message
=
(
"XML does not have
%
d match(es) for xpath '
%
s'
\n
XML:
%
s
\n
Context:
%
s"
%
(
exact_num
,
str
(
xpath
),
etree
.
tostring
(
xml_root
),
str
(
context_dict
)))
self
.
assertEqual
(
len
(
xml_root
.
xpath
(
xpath
)),
exact_num
,
msg
=
message
)
def
assert_no_xpath
(
self
,
xml_root
,
xpath
,
context_dict
):
"""Asserts that the xml tree does NOT have an element
satisfying `xpath`.
`xml_root` is an etree XML element
`xpath` is an XPath string, such as `'/foo/bar'`
`context` is used to print a debugging message
"""
self
.
assert_has_xpath
(
xml_root
,
xpath
,
context_dict
,
exact_num
=
0
)
class
TestChoiceGroupTemplate
(
TemplateTestCase
):
"""Test mako template for `<choicegroup>` input"""
TEMPLATE_NAME
=
'choicegroup.html'
def
setUp
(
self
):
choices
=
[(
'1'
,
'choice 1'
),
(
'2'
,
'choice 2'
),
(
'3'
,
'choice 3'
)]
self
.
context
=
{
'id'
:
'1'
,
'choices'
:
choices
,
'status'
:
'correct'
,
'input_type'
:
'checkbox'
,
'name_array_suffix'
:
'1'
,
'value'
:
'3'
}
super
(
TestChoiceGroupTemplate
,
self
)
.
setUp
()
def
test_problem_marked_correct
(
self
):
"""Test conditions under which the entire problem
(not a particular option) is marked correct"""
self
.
context
[
'status'
]
=
'correct'
self
.
context
[
'input_type'
]
=
'checkbox'
self
.
context
[
'value'
]
=
[
'1'
,
'2'
]
# Should mark the entire problem correct
xml
=
self
.
render_to_xml
(
self
.
context
)
xpath
=
"//div[@class='indicator_container']/span[@class='correct']"
self
.
assert_has_xpath
(
xml
,
xpath
,
self
.
context
)
# Should NOT mark individual options
self
.
assert_no_xpath
(
xml
,
"//label[@class='choicegroup_incorrect']"
,
self
.
context
)
self
.
assert_no_xpath
(
xml
,
"//label[@class='choicegroup_correct']"
,
self
.
context
)
def
test_problem_marked_incorrect
(
self
):
"""Test all conditions under which the entire problem
(not a particular option) is marked incorrect"""
conditions
=
[
{
'status'
:
'incorrect'
,
'input_type'
:
'radio'
,
'value'
:
''
},
{
'status'
:
'incorrect'
,
'input_type'
:
'checkbox'
,
'value'
:
[]},
{
'status'
:
'incorrect'
,
'input_type'
:
'checkbox'
,
'value'
:
[
'2'
]},
{
'status'
:
'incorrect'
,
'input_type'
:
'checkbox'
,
'value'
:
[
'2'
,
'3'
]},
{
'status'
:
'incomplete'
,
'input_type'
:
'radio'
,
'value'
:
''
},
{
'status'
:
'incomplete'
,
'input_type'
:
'checkbox'
,
'value'
:
[]},
{
'status'
:
'incomplete'
,
'input_type'
:
'checkbox'
,
'value'
:
[
'2'
]},
{
'status'
:
'incomplete'
,
'input_type'
:
'checkbox'
,
'value'
:
[
'2'
,
'3'
]}]
for
test_conditions
in
conditions
:
self
.
context
.
update
(
test_conditions
)
xml
=
self
.
render_to_xml
(
self
.
context
)
xpath
=
"//div[@class='indicator_container']/span[@class='incorrect']"
self
.
assert_has_xpath
(
xml
,
xpath
,
self
.
context
)
# Should NOT mark individual options
self
.
assert_no_xpath
(
xml
,
"//label[@class='choicegroup_incorrect']"
,
self
.
context
)
self
.
assert_no_xpath
(
xml
,
"//label[@class='choicegroup_correct']"
,
self
.
context
)
def
test_problem_marked_unanswered
(
self
):
"""Test all conditions under which the entire problem
(not a particular option) is marked unanswered"""
conditions
=
[
{
'status'
:
'unsubmitted'
,
'input_type'
:
'radio'
,
'value'
:
''
},
{
'status'
:
'unsubmitted'
,
'input_type'
:
'radio'
,
'value'
:
[]},
{
'status'
:
'unsubmitted'
,
'input_type'
:
'checkbox'
,
'value'
:
[]},
{
'input_type'
:
'radio'
,
'value'
:
''
},
{
'input_type'
:
'radio'
,
'value'
:
[]},
{
'input_type'
:
'checkbox'
,
'value'
:
[]},
{
'input_type'
:
'checkbox'
,
'value'
:
[
'1'
]},
{
'input_type'
:
'checkbox'
,
'value'
:
[
'1'
,
'2'
]}]
self
.
context
[
'status'
]
=
'unanswered'
for
test_conditions
in
conditions
:
self
.
context
.
update
(
test_conditions
)
xml
=
self
.
render_to_xml
(
self
.
context
)
xpath
=
"//div[@class='indicator_container']/span[@class='unanswered']"
self
.
assert_has_xpath
(
xml
,
xpath
,
self
.
context
)
# Should NOT mark individual options
self
.
assert_no_xpath
(
xml
,
"//label[@class='choicegroup_incorrect']"
,
self
.
context
)
self
.
assert_no_xpath
(
xml
,
"//label[@class='choicegroup_correct']"
,
self
.
context
)
def
test_option_marked_correct
(
self
):
"""Test conditions under which a particular option
(not the entire problem) is marked correct."""
conditions
=
[
{
'input_type'
:
'radio'
,
'value'
:
'2'
},
{
'input_type'
:
'radio'
,
'value'
:
[
'2'
]}]
self
.
context
[
'status'
]
=
'correct'
for
test_conditions
in
conditions
:
self
.
context
.
update
(
test_conditions
)
xml
=
self
.
render_to_xml
(
self
.
context
)
xpath
=
"//label[@class='choicegroup_correct']"
self
.
assert_has_xpath
(
xml
,
xpath
,
self
.
context
)
# Should NOT mark the whole problem
xpath
=
"//div[@class='indicator_container']/span"
self
.
assert_no_xpath
(
xml
,
xpath
,
self
.
context
)
def
test_option_marked_incorrect
(
self
):
"""Test conditions under which a particular option
(not the entire problem) is marked incorrect."""
conditions
=
[
{
'input_type'
:
'radio'
,
'value'
:
'2'
},
{
'input_type'
:
'radio'
,
'value'
:
[
'2'
]}]
self
.
context
[
'status'
]
=
'incorrect'
for
test_conditions
in
conditions
:
self
.
context
.
update
(
test_conditions
)
xml
=
self
.
render_to_xml
(
self
.
context
)
xpath
=
"//label[@class='choicegroup_incorrect']"
self
.
assert_has_xpath
(
xml
,
xpath
,
self
.
context
)
# Should NOT mark the whole problem
xpath
=
"//div[@class='indicator_container']/span"
self
.
assert_no_xpath
(
xml
,
xpath
,
self
.
context
)
def
test_never_show_correctness
(
self
):
"""Test conditions under which we tell the template to
NOT show correct/incorrect, but instead show a message.
This is used, for example, by the Justice course to ask
questions without specifying a correct answer. When
the student responds, the problem displays "Thank you
for your response"
"""
conditions
=
[
{
'input_type'
:
'radio'
,
'status'
:
'correct'
,
'value'
:
''
},
{
'input_type'
:
'radio'
,
'status'
:
'correct'
,
'value'
:
'2'
},
{
'input_type'
:
'radio'
,
'status'
:
'correct'
,
'value'
:
[
'2'
]},
{
'input_type'
:
'radio'
,
'status'
:
'incorrect'
,
'value'
:
'2'
},
{
'input_type'
:
'radio'
,
'status'
:
'incorrect'
,
'value'
:
[]},
{
'input_type'
:
'radio'
,
'status'
:
'incorrect'
,
'value'
:
[
'2'
]},
{
'input_type'
:
'checkbox'
,
'status'
:
'correct'
,
'value'
:
[]},
{
'input_type'
:
'checkbox'
,
'status'
:
'correct'
,
'value'
:
[
'2'
]},
{
'input_type'
:
'checkbox'
,
'status'
:
'incorrect'
,
'value'
:
[]},
{
'input_type'
:
'checkbox'
,
'status'
:
'incorrect'
,
'value'
:
[
'2'
]}]
self
.
context
[
'show_correctness'
]
=
'never'
self
.
context
[
'submitted_message'
]
=
'Test message'
for
test_conditions
in
conditions
:
self
.
context
.
update
(
test_conditions
)
xml
=
self
.
render_to_xml
(
self
.
context
)
# Should NOT mark the entire problem correct/incorrect
xpath
=
"//div[@class='indicator_container']/span[@class='correct']"
self
.
assert_no_xpath
(
xml
,
xpath
,
self
.
context
)
xpath
=
"//div[@class='indicator_container']/span[@class='incorrect']"
self
.
assert_no_xpath
(
xml
,
xpath
,
self
.
context
)
# Should NOT mark individual options
self
.
assert_no_xpath
(
xml
,
"//label[@class='choicegroup_incorrect']"
,
self
.
context
)
self
.
assert_no_xpath
(
xml
,
"//label[@class='choicegroup_correct']"
,
self
.
context
)
# Expect to see the message
message_elements
=
xml
.
xpath
(
"//div[@class='capa_alert']"
)
self
.
assertEqual
(
len
(
message_elements
),
1
)
self
.
assertEqual
(
message_elements
[
0
]
.
text
,
self
.
context
[
'submitted_message'
])
def
test_no_message_before_submission
(
self
):
"""Ensure that we don't show the `submitted_message`
before submitting"""
conditions
=
[
{
'input_type'
:
'radio'
,
'status'
:
'unsubmitted'
,
'value'
:
''
},
{
'input_type'
:
'radio'
,
'status'
:
'unsubmitted'
,
'value'
:
[]},
{
'input_type'
:
'checkbox'
,
'status'
:
'unsubmitted'
,
'value'
:
[]},
# These tests expose bug #365
# When the bug is fixed, uncomment these cases.
#{'input_type': 'radio', 'status': 'unsubmitted', 'value': '2'},
#{'input_type': 'radio', 'status': 'unsubmitted', 'value': ['2']},
#{'input_type': 'radio', 'status': 'unsubmitted', 'value': '2'},
#{'input_type': 'radio', 'status': 'unsubmitted', 'value': ['2']},
#{'input_type': 'checkbox', 'status': 'unsubmitted', 'value': ['2']},
#{'input_type': 'checkbox', 'status': 'unsubmitted', 'value': ['2']}]
]
self
.
context
[
'show_correctness'
]
=
'never'
self
.
context
[
'submitted_message'
]
=
'Test message'
for
test_conditions
in
conditions
:
self
.
context
.
update
(
test_conditions
)
xml
=
self
.
render_to_xml
(
self
.
context
)
# Expect that we do NOT see the message yet
self
.
assert_no_xpath
(
xml
,
"//div[@class='capa_alert']"
,
self
.
context
)
common/lib/xmodule/xmodule/tests/test_capa_module.py
View file @
e5e0dc4b
"""Tests of the Capa XModule"""
#pylint: disable=C0111
#pylint: disable=R0904
#pylint: disable=C0103
#pylint: disable=C0302
import
datetime
import
json
from
mock
import
Mock
,
MagicMock
,
patch
from
pprint
import
pprint
from
mock
import
Mock
,
patch
import
unittest
import
random
import
xmodule
import
capa
from
capa.responsetypes
import
StudentInputError
,
\
LoncapaProblemError
,
ResponseError
from
xmodule.capa_module
import
CapaModule
from
xmodule.modulestore
import
Location
from
lxml
import
etree
from
django.http
import
QueryDict
...
...
@@ -384,7 +386,7 @@ class CapaModuleTest(unittest.TestCase):
# what the input is, by patching CorrectMap.is_correct()
# Also simulate rendering the HTML
# TODO: pep8 thinks the following line has invalid syntax
with
patch
(
'capa.correctmap.CorrectMap.is_correct'
)
as
mock_is_correct
,
\
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"
...
...
@@ -435,8 +437,11 @@ class CapaModuleTest(unittest.TestCase):
self
.
assertEqual
(
module
.
attempts
,
3
)
def
test_check_problem_resubmitted_with_randomize
(
self
):
rerandomize_values
=
[
'always'
,
'true'
]
for
rerandomize
in
rerandomize_values
:
# Randomize turned on
module
=
CapaFactory
.
create
(
rerandomize
=
'always'
,
attempts
=
0
)
module
=
CapaFactory
.
create
(
rerandomize
=
rerandomize
,
attempts
=
0
)
# Simulate that the problem is completed
module
.
done
=
True
...
...
@@ -450,8 +455,11 @@ class CapaModuleTest(unittest.TestCase):
self
.
assertEqual
(
module
.
attempts
,
0
)
def
test_check_problem_resubmitted_no_randomize
(
self
):
rerandomize_values
=
[
'never'
,
'false'
,
'per_student'
]
for
rerandomize
in
rerandomize_values
:
# Randomize turned off
module
=
CapaFactory
.
create
(
rerandomize
=
'never'
,
attempts
=
0
,
done
=
True
)
module
=
CapaFactory
.
create
(
rerandomize
=
rerandomize
,
attempts
=
0
,
done
=
True
)
# Expect that we can submit successfully
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
...
...
@@ -615,7 +623,12 @@ class CapaModuleTest(unittest.TestCase):
self
.
assertTrue
(
'success'
in
result
and
not
result
[
'success'
])
def
test_save_problem_submitted_with_randomize
(
self
):
module
=
CapaFactory
.
create
(
rerandomize
=
'always'
,
done
=
True
)
# Capa XModule treats 'always' and 'true' equivalently
rerandomize_values
=
[
'always'
,
'true'
]
for
rerandomize
in
rerandomize_values
:
module
=
CapaFactory
.
create
(
rerandomize
=
rerandomize
,
done
=
True
)
# Try to save
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
...
...
@@ -625,7 +638,12 @@ class CapaModuleTest(unittest.TestCase):
self
.
assertTrue
(
'success'
in
result
and
not
result
[
'success'
])
def
test_save_problem_submitted_no_randomize
(
self
):
module
=
CapaFactory
.
create
(
rerandomize
=
'never'
,
done
=
True
)
# Capa XModule treats 'false' and 'per_student' equivalently
rerandomize_values
=
[
'never'
,
'false'
,
'per_student'
]
for
rerandomize
in
rerandomize_values
:
module
=
CapaFactory
.
create
(
rerandomize
=
rerandomize
,
done
=
True
)
# Try to save
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
...
...
@@ -681,21 +699,30 @@ class CapaModuleTest(unittest.TestCase):
# If user submitted a problem but hasn't reset,
# do NOT show the check button
# Note: we can only reset when rerandomize="always"
# Note: we can only reset when rerandomize="always"
or "true"
module
=
CapaFactory
.
create
(
rerandomize
=
"always"
,
done
=
True
)
self
.
assertFalse
(
module
.
should_show_check_button
())
module
=
CapaFactory
.
create
(
rerandomize
=
"true"
,
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
# Setting rerandomize to "never"
or "false"
ensures that the reset button
# is not shown
module
=
CapaFactory
.
create
(
rerandomize
=
"never"
,
done
=
True
)
self
.
assertTrue
(
module
.
should_show_check_button
())
module
=
CapaFactory
.
create
(
rerandomize
=
"false"
,
done
=
True
)
self
.
assertTrue
(
module
.
should_show_check_button
())
module
=
CapaFactory
.
create
(
rerandomize
=
"per_student"
,
done
=
True
)
self
.
assertTrue
(
module
.
should_show_check_button
())
def
test_should_show_reset_button
(
self
):
attempts
=
random
.
randint
(
1
,
10
)
...
...
@@ -712,6 +739,14 @@ class CapaModuleTest(unittest.TestCase):
module
=
CapaFactory
.
create
(
rerandomize
=
"never"
,
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
=
"per_student"
,
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
=
"false"
,
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
(
done
=
False
)
...
...
@@ -742,13 +777,19 @@ class CapaModuleTest(unittest.TestCase):
module
=
CapaFactory
.
create
(
rerandomize
=
"always"
,
done
=
True
)
self
.
assertFalse
(
module
.
should_show_save_button
())
module
=
CapaFactory
.
create
(
rerandomize
=
"true"
,
done
=
True
)
self
.
assertFalse
(
module
.
should_show_save_button
())
# If the user has unlimited attempts and we are not randomizing,
# then do NOT show a save button
# because they can keep using "Check"
module
=
CapaFactory
.
create
(
max_attempts
=
None
,
rerandomize
=
"never"
,
done
=
False
)
self
.
assertFalse
(
module
.
should_show_save_button
())
module
=
CapaFactory
.
create
(
max_attempts
=
None
,
rerandomize
=
"never"
,
done
=
True
)
module
=
CapaFactory
.
create
(
max_attempts
=
None
,
rerandomize
=
"false"
,
done
=
True
)
self
.
assertFalse
(
module
.
should_show_save_button
())
module
=
CapaFactory
.
create
(
max_attempts
=
None
,
rerandomize
=
"per_student"
,
done
=
True
)
self
.
assertFalse
(
module
.
should_show_save_button
())
# Otherwise, DO show the save button
...
...
@@ -759,6 +800,12 @@ class CapaModuleTest(unittest.TestCase):
module
=
CapaFactory
.
create
(
rerandomize
=
"never"
,
max_attempts
=
2
,
done
=
True
)
self
.
assertTrue
(
module
.
should_show_save_button
())
module
=
CapaFactory
.
create
(
rerandomize
=
"false"
,
max_attempts
=
2
,
done
=
True
)
self
.
assertTrue
(
module
.
should_show_save_button
())
module
=
CapaFactory
.
create
(
rerandomize
=
"per_student"
,
max_attempts
=
2
,
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
,
done
=
False
)
...
...
@@ -788,9 +835,15 @@ class CapaModuleTest(unittest.TestCase):
done
=
True
)
self
.
assertTrue
(
module
.
should_show_save_button
())
module
=
CapaFactory
.
create
(
force_save_button
=
"true"
,
rerandomize
=
"true"
,
done
=
True
)
self
.
assertTrue
(
module
.
should_show_save_button
())
def
test_no_max_attempts
(
self
):
module
=
CapaFactory
.
create
(
max_attempts
=
''
)
html
=
module
.
get_problem_html
()
self
.
assertTrue
(
html
is
not
None
)
# assert that we got here without exploding
def
test_get_problem_html
(
self
):
...
...
@@ -875,6 +928,8 @@ class CapaModuleTest(unittest.TestCase):
# Try to render the module with DEBUG turned off
html
=
module
.
get_problem_html
()
self
.
assertTrue
(
html
is
not
None
)
# Check the rendering context
render_args
,
_
=
module
.
system
.
render_template
.
call_args
context
=
render_args
[
1
]
...
...
@@ -886,7 +941,9 @@ class CapaModuleTest(unittest.TestCase):
def
test_random_seed_no_change
(
self
):
# Run the test for each possible rerandomize value
for
rerandomize
in
[
'never'
,
'per_student'
,
'always'
,
'onreset'
]:
for
rerandomize
in
[
'false'
,
'never'
,
'per_student'
,
'always'
,
'true'
,
'onreset'
]:
module
=
CapaFactory
.
create
(
rerandomize
=
rerandomize
)
# Get the seed
...
...
@@ -896,8 +953,9 @@ class CapaModuleTest(unittest.TestCase):
# If we're not rerandomizing, the seed is always set
# to the same value (1)
if
rerandomize
==
'never'
:
self
.
assertEqual
(
seed
,
1
)
if
rerandomize
in
[
'never'
]:
self
.
assertEqual
(
seed
,
1
,
msg
=
"Seed should always be 1 when rerandomize='
%
s'"
%
rerandomize
)
# Check the problem
get_request_dict
=
{
CapaFactory
.
input_key
():
'3.14'
}
...
...
@@ -947,7 +1005,8 @@ class CapaModuleTest(unittest.TestCase):
return
success
# Run the test for each possible rerandomize value
for
rerandomize
in
[
'never'
,
'per_student'
,
'always'
,
'onreset'
]:
for
rerandomize
in
[
'never'
,
'false'
,
'per_student'
,
'always'
,
'true'
,
'onreset'
]:
module
=
CapaFactory
.
create
(
rerandomize
=
rerandomize
)
# Get the seed
...
...
@@ -959,7 +1018,7 @@ class CapaModuleTest(unittest.TestCase):
# is set to 'never' -- it should still be 1
# The seed also stays the same if we're randomizing
# 'per_student': the same student should see the same problem
if
rerandomize
in
[
'never'
,
'per_student'
]:
if
rerandomize
in
[
'never'
,
'
false'
,
'
per_student'
]:
self
.
assertEqual
(
seed
,
_reset_and_get_seed
(
module
))
# Otherwise, we expect the seed to change
...
...
@@ -969,10 +1028,8 @@ class CapaModuleTest(unittest.TestCase):
# Since there's a small chance we might get the
# same seed again, give it 5 chances
# to generate a different seed
success
=
_retry_and_check
(
5
,
lambda
:
_reset_and_get_seed
(
module
)
!=
seed
)
success
=
_retry_and_check
(
5
,
lambda
:
_reset_and_get_seed
(
module
)
!=
seed
)
# TODO: change this comparison to module.seed is not None?
self
.
assertTrue
(
module
.
seed
!=
None
)
self
.
assertTrue
(
module
.
seed
is
not
None
)
msg
=
'Could not get a new seed from reset after 5 tries'
self
.
assertTrue
(
success
,
msg
)
lms/djangoapps/courseware/features/problems.feature
View file @
e5e0dc4b
...
...
@@ -15,6 +15,7 @@ Feature: Answer problems
|
drop
down
|
|
multiple
choice
|
|
checkbox
|
|
radio
|
|
string
|
|
numerical
|
|
formula
|
...
...
@@ -33,6 +34,7 @@ Feature: Answer problems
|
drop
down
|
|
multiple
choice
|
|
checkbox
|
|
radio
|
|
string
|
|
numerical
|
|
formula
|
...
...
@@ -50,6 +52,7 @@ Feature: Answer problems
|
drop
down
|
|
multiple
choice
|
|
checkbox
|
|
radio
|
|
string
|
|
numerical
|
|
formula
|
...
...
@@ -71,6 +74,8 @@ Feature: Answer problems
|
multiple
choice
|
incorrect
|
|
checkbox
|
correct
|
|
checkbox
|
incorrect
|
|
radio
|
correct
|
|
radio
|
incorrect
|
|
string
|
correct
|
|
string
|
incorrect
|
|
numerical
|
correct
|
...
...
lms/djangoapps/courseware/features/problems.py
View file @
e5e0dc4b
...
...
@@ -42,7 +42,13 @@ PROBLEM_FACTORY_DICT = {
'choice_type'
:
'checkbox'
,
'choices'
:
[
True
,
False
,
True
,
False
,
False
],
'choice_names'
:
[
'Choice 1'
,
'Choice 2'
,
'Choice 3'
,
'Choice 4'
]}},
'radio'
:
{
'factory'
:
ChoiceResponseXMLFactory
(),
'kwargs'
:
{
'question_text'
:
'The correct answer is Choice 3'
,
'choice_type'
:
'radio'
,
'choices'
:
[
False
,
False
,
True
,
False
],
'choice_names'
:
[
'Choice 1'
,
'Choice 2'
,
'Choice 3'
,
'Choice 4'
]}},
'string'
:
{
'factory'
:
StringResponseXMLFactory
(),
'kwargs'
:
{
...
...
@@ -174,6 +180,12 @@ def answer_problem(step, problem_type, correctness):
else
:
inputfield
(
'checkbox'
,
choice
=
'choice_3'
)
.
check
()
elif
problem_type
==
'radio'
:
if
correctness
==
'correct'
:
inputfield
(
'radio'
,
choice
=
'choice_2'
)
.
check
()
else
:
inputfield
(
'radio'
,
choice
=
'choice_1'
)
.
check
()
elif
problem_type
==
'string'
:
textvalue
=
'correct string'
if
correctness
==
'correct'
\
else
'incorrect'
...
...
@@ -252,6 +264,14 @@ def assert_problem_has_answer(step, problem_type, answer_class):
else
:
assert_checked
(
'checkbox'
,
[])
elif
problem_type
==
"radio"
:
if
answer_class
==
'correct'
:
assert_checked
(
'radio'
,
[
'choice_2'
])
elif
answer_class
==
'incorrect'
:
assert_checked
(
'radio'
,
[
'choice_1'
])
else
:
assert_checked
(
'radio'
,
[])
elif
problem_type
==
'string'
:
if
answer_class
==
'blank'
:
expected
=
''
...
...
@@ -298,6 +318,7 @@ CORRECTNESS_SELECTORS = {
'correct'
:
{
'drop down'
:
[
'span.correct'
],
'multiple choice'
:
[
'label.choicegroup_correct'
],
'checkbox'
:
[
'span.correct'
],
'radio'
:
[
'label.choicegroup_correct'
],
'string'
:
[
'div.correct'
],
'numerical'
:
[
'div.correct'
],
'formula'
:
[
'div.correct'
],
...
...
@@ -308,6 +329,8 @@ CORRECTNESS_SELECTORS = {
'multiple choice'
:
[
'label.choicegroup_incorrect'
,
'span.incorrect'
],
'checkbox'
:
[
'span.incorrect'
],
'radio'
:
[
'label.choicegroup_incorrect'
,
'span.incorrect'
],
'string'
:
[
'div.incorrect'
],
'numerical'
:
[
'div.incorrect'
],
'formula'
:
[
'div.incorrect'
],
...
...
@@ -317,6 +340,7 @@ CORRECTNESS_SELECTORS = {
'unanswered'
:
{
'drop down'
:
[
'span.unanswered'
],
'multiple choice'
:
[
'span.unanswered'
],
'checkbox'
:
[
'span.unanswered'
],
'radio'
:
[
'span.unanswered'
],
'string'
:
[
'div.unanswered'
],
'numerical'
:
[
'div.unanswered'
],
'formula'
:
[
'div.unanswered'
],
...
...
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