add multiple correct values check for Dropdown problems
This commit is contained in:
@@ -245,6 +245,22 @@ class LoncapaProblem(object):
|
||||
This translation takes in the new format and synthesizes the old option= attribute
|
||||
so all downstream logic works unchanged with the new <option> tag format.
|
||||
"""
|
||||
def is_optioninput_valid(optioninput):
|
||||
"""
|
||||
Verifies if a given optioninput xml is valid or not.
|
||||
|
||||
A given optioninput(Dropdown) problem is invalid if it has more than one correct answer.
|
||||
|
||||
Argument:
|
||||
optioninput: dropdown specification tree
|
||||
Returns:
|
||||
boolean: signifying if the optioninput is valid or not.
|
||||
"""
|
||||
correct_options = [
|
||||
option.get('correct').upper() == 'TRUE' for option in optioninput.findall('./option')
|
||||
]
|
||||
return correct_options.count(True) in (0, 1)
|
||||
|
||||
additionals = tree.xpath('//stringresponse/additional_answer')
|
||||
for additional in additionals:
|
||||
answer = additional.get('answer')
|
||||
@@ -252,8 +268,9 @@ class LoncapaProblem(object):
|
||||
if not answer and text: # trigger of old->new conversion
|
||||
additional.set('answer', text)
|
||||
additional.text = ''
|
||||
|
||||
for optioninput in tree.xpath('//optioninput'):
|
||||
if not is_optioninput_valid(optioninput):
|
||||
raise responsetypes.LoncapaProblemError("Dropdown questions can only have one correct answer.")
|
||||
correct_option = None
|
||||
child_options = []
|
||||
for option_element in optioninput.findall('./option'):
|
||||
|
||||
@@ -12,6 +12,7 @@ from lxml import etree
|
||||
from markupsafe import Markup
|
||||
from mock import patch
|
||||
|
||||
from capa.responsetypes import LoncapaProblemError
|
||||
from capa.tests.helpers import new_loncapa_problem
|
||||
from openedx.core.djangolib.markup import HTML
|
||||
|
||||
@@ -460,6 +461,37 @@ class CAPAProblemTest(unittest.TestCase):
|
||||
self.assert_question_tag(question1, question2, tag='label', label_attr=False)
|
||||
self.assert_question_tag(question1, question2, tag='p', label_attr=True)
|
||||
|
||||
def test_optionresponse_xml_compatibility(self):
|
||||
"""
|
||||
Verify that an optionresponse problem with multiple correct answers is not instantiated.
|
||||
|
||||
Scenario:
|
||||
Given an optionresponse/Dropdown problem
|
||||
If there are multiple correct answers
|
||||
Then the problem is not instantiated
|
||||
And Loncapa problem error exception is raised
|
||||
If the problem is corrected by including only one correct answer
|
||||
Then the problem is created successfully
|
||||
"""
|
||||
xml = """
|
||||
<problem>
|
||||
<optionresponse>
|
||||
<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown problems. Edit this component to replace this template with your own assessment.</p>
|
||||
<label>Add the question text, or prompt, here. This text is required.</label>
|
||||
<description>You can add an optional tip or note related to the prompt like this. </description>
|
||||
<optioninput>
|
||||
<option correct="False">an incorrect answer</option>
|
||||
<option correct="True">the correct answer</option>
|
||||
<option correct="{correctness}">an incorrect answer</option>
|
||||
</optioninput>
|
||||
</optionresponse>
|
||||
</problem>
|
||||
"""
|
||||
with self.assertRaises(LoncapaProblemError):
|
||||
new_loncapa_problem(xml.format(correctness=True))
|
||||
problem = new_loncapa_problem(xml.format(correctness=False))
|
||||
self.assertIsNotNone(problem)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class CAPAMultiInputProblemTest(unittest.TestCase):
|
||||
|
||||
@@ -344,7 +344,7 @@ class ProblemBlock(
|
||||
|
||||
def max_score(self):
|
||||
"""
|
||||
Return the problem's max score
|
||||
Return the problem's max score if problem is instantiated successfully, else return max score of 0.
|
||||
"""
|
||||
from capa.capa_problem import LoncapaProblem, LoncapaSystem
|
||||
capa_system = LoncapaSystem(
|
||||
@@ -363,16 +363,22 @@ class ProblemBlock(
|
||||
xqueue=None,
|
||||
matlab_api_key=None,
|
||||
)
|
||||
lcp = LoncapaProblem(
|
||||
problem_text=self.data,
|
||||
id=self.location.html_id(),
|
||||
capa_system=capa_system,
|
||||
capa_module=self,
|
||||
state={},
|
||||
seed=1,
|
||||
minimal_init=True,
|
||||
)
|
||||
return lcp.get_max_score()
|
||||
try:
|
||||
lcp = LoncapaProblem(
|
||||
problem_text=self.data,
|
||||
id=self.location.html_id(),
|
||||
capa_system=capa_system,
|
||||
capa_module=self,
|
||||
state={},
|
||||
seed=1,
|
||||
minimal_init=True,
|
||||
)
|
||||
except responsetypes.LoncapaProblemError:
|
||||
log.exception(u"LcpFatalError for block {} while getting max score".format(str(self.location)))
|
||||
maximum_score = 0
|
||||
else:
|
||||
maximum_score = lcp.get_max_score()
|
||||
return maximum_score
|
||||
|
||||
def generate_report_data(self, user_state_iterator, limit_responses=None):
|
||||
"""
|
||||
|
||||
@@ -2871,6 +2871,27 @@ class ProblemBlockXMLTest(unittest.TestCase):
|
||||
with self.assertRaises(etree.XMLSyntaxError):
|
||||
self._create_descriptor(sample_invalid_xml, name="Invalid XML")
|
||||
|
||||
def test_invalid_dropdown_xml(self):
|
||||
"""
|
||||
Verify the capa problem cannot be created from dropdown xml with multiple correct answers.
|
||||
"""
|
||||
problem_xml = textwrap.dedent("""
|
||||
<problem>
|
||||
<optionresponse>
|
||||
<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for dropdown problems. Edit this component to replace this template with your own assessment.</p>
|
||||
<label>Add the question text, or prompt, here. This text is required.</label>
|
||||
<description>You can add an optional tip or note related to the prompt like this. </description>
|
||||
<optioninput>
|
||||
<option correct="False">an incorrect answer</option>
|
||||
<option correct="True">the correct answer</option>
|
||||
<option correct="True">an incorrect answer</option>
|
||||
</optioninput>
|
||||
</optionresponse>
|
||||
</problem>
|
||||
""")
|
||||
with self.assertRaises(Exception):
|
||||
CapaFactory.create(xml=problem_xml)
|
||||
|
||||
|
||||
class ComplexEncoderTest(unittest.TestCase):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user