""" Tests the logic of the "targeted-feedback" attribute for MultipleChoice questions, i.e. those with the element """ import textwrap import unittest from xmodule.capa.tests.helpers import load_fixture, new_loncapa_problem, mock_capa_system class CapaTargetedFeedbackTest(unittest.TestCase): ''' Testing class ''' def setUp(self): super(CapaTargetedFeedbackTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments self.system = mock_capa_system() def test_no_targeted_feedback(self): xml_str = textwrap.dedent("""

What is the correct answer?

wrong-1 wrong-2 correct-1 wrong-3

Targeted Feedback

This is the 1st WRONG solution

Targeted Feedback

This is the 2nd WRONG solution

Targeted Feedback

This is the 3rd WRONG solution

Targeted Feedback

Feedback on your correct solution...

Explanation

This is the solution explanation

Not much to explain here, sorry!

""") problem = new_loncapa_problem(xml_str) the_html = problem.get_html() without_new_lines = the_html.replace("\n", "") self.assertRegex(without_new_lines, r"
.*'wrong-1'.*'wrong-2'.*'correct-1'.*'wrong-3'.*
") self.assertRegex(without_new_lines, r"feedback1|feedback2|feedback3|feedbackC") def test_targeted_feedback_not_finished(self): problem = new_loncapa_problem(load_fixture('targeted_feedback.xml')) the_html = problem.get_html() without_new_lines = the_html.replace("\n", "") self.assertRegex(without_new_lines, r"
.*'wrong-1'.*'wrong-2'.*'correct-1'.*'wrong-3'.*
") self.assertNotRegex(without_new_lines, r"feedback1|feedback2|feedback3|feedbackC") assert the_html == problem.get_html(), 'Should be able to call get_html() twice' def test_targeted_feedback_student_answer1(self): problem = new_loncapa_problem(load_fixture('targeted_feedback.xml')) problem.done = True problem.student_answers = {'1_2_1': 'choice_3'} the_html = problem.get_html() without_new_lines = the_html.replace("\\n", "").replace("\n", "") # pylint: disable=line-too-long self.assertRegex(without_new_lines, r"\s*Incorrect.*3rd WRONG solution") self.assertNotRegex(without_new_lines, r"feedback1|feedback2|feedbackC") # Check that calling it multiple times yields the same thing the_html2 = problem.get_html() assert the_html == the_html2 def test_targeted_feedback_student_answer2(self): problem = new_loncapa_problem(load_fixture('targeted_feedback.xml')) problem.done = True problem.student_answers = {'1_2_1': 'choice_0'} the_html = problem.get_html() without_new_lines = the_html.replace("\\n", "").replace("\n", "") # pylint: disable=line-too-long self.assertRegex(without_new_lines, r"\s*Incorrect.*1st WRONG solution") self.assertRegex(without_new_lines, r"
\{.*'1_solution_1'.*\}
") self.assertNotRegex(without_new_lines, r"feedback2|feedback3|feedbackC") def test_targeted_feedback_correct_answer(self): """ Test the case of targeted feedback for a correct answer. """ problem = new_loncapa_problem(load_fixture('targeted_feedback.xml')) problem.done = True problem.student_answers = {'1_2_1': 'choice_2'} the_html = problem.get_html() without_new_lines = the_html.replace("\\n", "").replace("\n", "") # pylint: disable=line-too-long self.assertRegex(without_new_lines, r"\s*Correct.*Feedback on your correct solution...") self.assertNotRegex(without_new_lines, r"feedback1|feedback2|feedback3") def test_targeted_feedback_id_typos(self): """Cases where the explanation-id's don't match anything.""" xml_str = textwrap.dedent("""

What is the correct answer?

wrong-1 wrong-2 correct-1 wrong-3

Targeted Feedback

This is the 1st WRONG solution

Targeted Feedback

This is the 2nd WRONG solution

Targeted Feedback

This is the 3rd WRONG solution

Targeted Feedback

Feedback on your correct solution...

Explanation

This is the solution explanation

Not much to explain here, sorry!

""") # explanation-id does not match anything: fall back to empty targetedfeedbackset problem = new_loncapa_problem(xml_str) problem.done = True problem.student_answers = {'1_2_1': 'choice_0'} the_html = problem.get_html() self.assertRegex(the_html, r"\s*") # New problem with same XML -- try the correct choice. problem = new_loncapa_problem(xml_str) problem.done = True problem.student_answers = {'1_2_1': 'choice_2'} # correct the_html = problem.get_html() self.assertRegex(the_html, r"\s*") def test_targeted_feedback_no_solution_element(self): xml_str = textwrap.dedent("""

What is the correct answer?

wrong-1 wrong-2 correct-1 wrong-3

Targeted Feedback

""") # Solution element not found problem = new_loncapa_problem(xml_str) problem.done = True problem.student_answers = {'1_2_1': 'choice_2'} the_html = problem.get_html() without_new_lines = the_html.replace("\n", "") # right after self.assertRegex( without_new_lines, r"
.*.*\s*
" ) def test_targeted_feedback_show_solution_explanation(self): xml_str = textwrap.dedent("""

What is the correct answer?

wrong-1 wrong-2 correct-1 wrong-3

Targeted Feedback

This is the 1st WRONG solution

Targeted Feedback

This is the 2nd WRONG solution

Targeted Feedback

This is the 3rd WRONG solution

Targeted Feedback

Feedback on your correct solution...

Explanation

This is the solution explanation

Not much to explain here, sorry!

""") problem = new_loncapa_problem(xml_str) problem.done = True problem.student_answers = {'1_2_1': 'choice_0'} the_html = problem.get_html() without_new_lines = the_html.replace("\n", "") # pylint: disable=line-too-long self.assertRegex(without_new_lines, r".*1st WRONG solution") self.assertRegex(without_new_lines, r"\{.*'1_solution_1'.*\}") self.assertNotRegex(without_new_lines, r"feedback2|feedback3") # Check that calling it multiple times yields the same thing the_html2 = problem.get_html() assert the_html == the_html2 def test_targeted_feedback_no_show_solution_explanation(self): xml_str = textwrap.dedent("""

What is the correct answer?

wrong-1 wrong-2 correct-1 wrong-3

Targeted Feedback

This is the 1st WRONG solution

Targeted Feedback

This is the 2nd WRONG solution

Targeted Feedback

This is the 3rd WRONG solution

Targeted Feedback

Feedback on your correct solution...

Explanation

This is the solution explanation

Not much to explain here, sorry!

""") problem = new_loncapa_problem(xml_str) problem.done = True problem.student_answers = {'1_2_1': 'choice_0'} the_html = problem.get_html() without_new_lines = the_html.replace("\n", "") # pylint: disable=line-too-long self.assertRegex(without_new_lines, r".*1st WRONG solution") self.assertNotRegex(without_new_lines, r"\{.*'1_solution_1'.*\}") self.assertNotRegex(without_new_lines, r"feedback2|feedback3|feedbackC") def test_targeted_feedback_with_solutionset_explanation(self): xml_str = textwrap.dedent("""

What is the correct answer?

wrong-1 wrong-2 correct-1 wrong-3 correct-2

Targeted Feedback

This is the 1st WRONG solution

Targeted Feedback

This is the 2nd WRONG solution

Targeted Feedback

This is the 3rd WRONG solution

Targeted Feedback

Feedback on your correct solution...

Targeted Feedback

Feedback on the other solution...

Explanation

This is the other solution explanation

Not much to explain here, sorry!

""") problem = new_loncapa_problem(xml_str) problem.done = True problem.student_answers = {'1_2_1': 'choice_0'} the_html = problem.get_html() without_new_lines = the_html.replace("\n", "") # pylint: disable=line-too-long self.assertRegex(without_new_lines, r".*1st WRONG solution") self.assertRegex(without_new_lines, r"\{.*'1_solution_1'.*\}") self.assertNotRegex(without_new_lines, r"feedback2|feedback3") def test_targeted_feedback_no_feedback_for_selected_choice1(self): xml_str = textwrap.dedent("""

What is the correct answer?

wrong-1 wrong-2 correct-1 wrong-3

Targeted Feedback

This is the 1st WRONG solution

Targeted Feedback

This is the 3rd WRONG solution

Targeted Feedback

Feedback on your correct solution...

Explanation

This is the solution explanation

Not much to explain here, sorry!

""") # The student choses one with no feedback, but alwaysShowCorrectChoiceExplanation # is in force, so we should see the correct solution feedback. problem = new_loncapa_problem(xml_str) problem.done = True problem.student_answers = {'1_2_1': 'choice_1'} the_html = problem.get_html() without_new_lines = the_html.replace("\n", "") self.assertRegex(without_new_lines, r"\{.*'1_solution_1'.*\}") self.assertNotRegex(without_new_lines, r"feedback1|feedback3") def test_targeted_feedback_no_feedback_for_selected_choice2(self): xml_str = textwrap.dedent("""

What is the correct answer?

wrong-1 wrong-2 correct-1 wrong-3

Targeted Feedback

This is the 1st WRONG solution

Targeted Feedback

This is the 3rd WRONG solution

Targeted Feedback

Feedback on your correct solution...

Explanation

This is the solution explanation

Not much to explain here, sorry!

""") # The student chooses one with no feedback set, so we check that there's no feedback. problem = new_loncapa_problem(xml_str) problem.done = True problem.student_answers = {'1_2_1': 'choice_1'} the_html = problem.get_html() without_new_lines = the_html.replace("\n", "") self.assertNotRegex(without_new_lines, r"\{.*'1_solution_1'.*\}") self.assertNotRegex(without_new_lines, r"feedback1|feedback3|feedbackC") def test_targeted_feedback_multiple_not_answered(self): # Not answered -> empty targeted feedback problem = new_loncapa_problem(load_fixture('targeted_feedback_multiple.xml')) the_html = problem.get_html() without_new_lines = the_html.replace("\n", "") # Q1 and Q2 have no feedback self.assertRegex( without_new_lines, r'\s*.*\s*' ) def test_targeted_feedback_multiple_answer_1(self): problem = new_loncapa_problem(load_fixture('targeted_feedback_multiple.xml')) problem.done = True problem.student_answers = {'1_2_1': 'choice_0'} # feedback1 the_html = problem.get_html() without_new_lines = the_html.replace("\n", "") # Q1 has feedback1 and Q2 has nothing self.assertRegex( without_new_lines, r'.*?explanation-id="feedback1".*?.*' + r'\s*' ) def test_targeted_feedback_multiple_answer_2(self): problem = new_loncapa_problem(load_fixture('targeted_feedback_multiple.xml')) problem.done = True problem.student_answers = {'1_2_1': 'choice_0', '1_3_1': 'choice_2'} # Q1 wrong, Q2 correct the_html = problem.get_html() without_new_lines = the_html.replace("\n", "") # Q1 has feedback1 and Q2 has feedbackC self.assertRegex( without_new_lines, r'.*?explanation-id="feedback1".*?.*' + r'.*explanation-id="feedbackC".*?' )