add multiple correct values check for Dropdown problems

This commit is contained in:
DawoudSheraz
2020-01-28 12:03:13 +05:00
parent 2e71793ba5
commit 0b1c7db967
6 changed files with 159 additions and 12 deletions

View File

@@ -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'):

View File

@@ -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):

View File

@@ -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):
"""

View File

@@ -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):