""" Tests the logic of the "answer-pool" attribute, e.g. """ import textwrap import unittest from xmodule.capa.responsetypes import LoncapaProblemError from xmodule.capa.tests.helpers import mock_capa_system, new_loncapa_problem class CapaAnswerPoolTest(unittest.TestCase): """Capa Answer Pool Test""" def setUp(self): super().setUp() self.system = mock_capa_system() # XML problem setup used by a few tests. common_question_xml = textwrap.dedent( """

What is the correct answer?

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

Explanation

This is the 1st solution

Not much to explain here, sorry!

Explanation

This is the 2nd solution

""" ) def test_answer_pool_4_choices_1_multiplechoiceresponse_seed1(self): """Test answer-pool=4 with one multiplechoiceresponse and a fixed seed.""" problem = new_loncapa_problem(self.common_question_xml, seed=723) the_html = problem.get_html() # [('choice_3', 'wrong-3'), ('choice_5', 'correct-2'), ('choice_1', 'wrong-2'), ('choice_4', 'wrong-4')] self.assertRegex(the_html, r"
.*\[.*'wrong-3'.*'correct-2'.*'wrong-2'.*'wrong-4'.*\].*
") self.assertRegex(the_html, r"
\{.*'1_solution_2'.*\}
") assert the_html == problem.get_html(), "should be able to call get_html() twice" # Check about masking response = list(problem.responders.values())[0] assert not response.has_mask() assert response.has_answerpool() assert response.unmask_order() == ["choice_3", "choice_5", "choice_1", "choice_4"] def test_answer_pool_4_choices_1_multiplechoiceresponse_seed2(self): """Test answer-pool=4 with one multiplechoiceresponse and a different seed.""" problem = new_loncapa_problem(self.common_question_xml, seed=9) the_html = problem.get_html() # [('choice_0', 'wrong-1'), ('choice_4', 'wrong-4'), ('choice_3', 'wrong-3'), ('choice_2', 'correct-1')] self.assertRegex(the_html, r"
.*\[.*'wrong-1'.*'wrong-4'.*'wrong-3'.*'correct-1'.*\].*
") self.assertRegex(the_html, r"
\{.*'1_solution_1'.*\}
") # Check about masking response = list(problem.responders.values())[0] assert not response.has_mask() assert hasattr(response, "has_answerpool") assert response.unmask_order() == ["choice_0", "choice_4", "choice_3", "choice_2"] def test_no_answer_pool_4_choices_1_multiplechoiceresponse(self): """Test behavior when no answer-pool attribute is provided.""" xml_str = textwrap.dedent( """

What is the correct answer?

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

Explanation

This is the 1st solution

Not much to explain here, sorry!

Explanation

This is the 2nd solution

""" ) problem = new_loncapa_problem(xml_str) the_html = problem.get_html() self.assertRegex( the_html, r"
.*\[.*'wrong-1'.*'wrong-2'.*'correct-1'.*'wrong-3'.*'wrong-4'.*'correct-2'.*\].*
" ) self.assertRegex(the_html, r"
\{.*'1_solution_1'.*'1_solution_2'.*\}
") assert the_html == problem.get_html(), "should be able to call get_html() twice" # Check about masking response = list(problem.responders.values())[0] assert not response.has_mask() assert not response.has_answerpool() def test_0_answer_pool_4_choices_1_multiplechoiceresponse(self): """Test behavior when answer-pool is explicitly set to 0.""" xml_str = textwrap.dedent( """

What is the correct answer?

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

Explanation

This is the 1st solution

Not much to explain here, sorry!

Explanation

This is the 2nd solution

""" ) problem = new_loncapa_problem(xml_str) the_html = problem.get_html() self.assertRegex( the_html, r"
.*\[.*'wrong-1'.*'wrong-2'.*'correct-1'.*'wrong-3'.*'wrong-4'.*'correct-2'.*\].*
" ) self.assertRegex(the_html, r"
\{.*'1_solution_1'.*'1_solution_2'.*\}
") response = list(problem.responders.values())[0] assert not response.has_mask() assert not response.has_answerpool() def test_invalid_answer_pool_value(self): """Ensure error is raised for non-integer answer-pool values.""" xml_str = textwrap.dedent( """

What is the correct answer?

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

Explanation

This is the 1st solution

Not much to explain here, sorry!

Explanation

This is the 2nd solution

""" ) with self.assertRaisesRegex(LoncapaProblemError, "answer-pool"): new_loncapa_problem(xml_str) def test_invalid_answer_pool_none_correct(self): """Ensure error is raised if no correct choice exists in answer-pool.""" xml_str = textwrap.dedent( """

What is the correct answer?

wrong-1 wrong-2 wrong!! wrong-3 wrong-4
""" ) with self.assertRaisesRegex(LoncapaProblemError, "1 correct.*1 incorrect"): new_loncapa_problem(xml_str) def test_invalid_answer_pool_all_correct(self): """Ensure error is raised if all choices are marked correct in answer-pool.""" xml_str = textwrap.dedent( """

What is the correct answer?

!wrong-1 !wrong-2 !wrong-3 !wrong-4
""" ) with self.assertRaisesRegex(LoncapaProblemError, "1 correct.*1 incorrect"): new_loncapa_problem(xml_str) def test_answer_pool_5_choices_1_multiplechoiceresponse_seed1(self): """Test answer-pool=5 with one multiplechoiceresponse and fixed seed.""" xml_str = textwrap.dedent( """

What is the correct answer?

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

Explanation

This is the 1st solution

Not much to explain here, sorry!

Explanation

This is the 2nd solution

""" ) problem = new_loncapa_problem(xml_str, seed=723) the_html = problem.get_html() self.assertRegex(the_html, r"
.*\[.*'correct-2'.*'wrong-1'.*'wrong-2'.*.*'wrong-3'.*'wrong-4'.*\].*
") self.assertRegex(the_html, r"
\{.*'1_solution_2'.*\}
") response = list(problem.responders.values())[0] assert not response.has_mask() assert response.unmask_order() == ["choice_5", "choice_0", "choice_1", "choice_3", "choice_4"] def test_answer_pool_2_multiplechoiceresponses_seed1(self): """Test two multiplechoiceresponses with different answer-pools and fixed seed.""" xml_str = textwrap.dedent( """

What is the correct answer?

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

Explanation

This is the 1st solution

Not much to explain here, sorry!

Explanation

This is the 2nd solution

What is the correct answer?

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

Explanation

This is the 1st solution

Not much to explain here, sorry!

Explanation

This is the 2nd solution

""" ) problem = new_loncapa_problem(xml_str) the_html = problem.get_html() str1 = r"
.*\[.*'wrong-3'.*'correct-2'.*'wrong-2'.*'wrong-4'.*\].*
" str2 = r"
.*\[.*'wrong-2'.*'wrong-1'.*'correct-2'.*\].*
" # rng shared # str2 = r"
.*\[.*'correct-2'.*'wrong-2'.*'wrong-3'.*\].*
" # rng independent str3 = r"
\{.*'1_solution_2'.*\}
" str4 = r"
\{.*'1_solution_4'.*\}
" self.assertRegex(the_html, str1) self.assertRegex(the_html, str2) self.assertRegex(the_html, str3) self.assertRegex(the_html, str4) without_new_lines = the_html.replace("\n", "") self.assertRegex(without_new_lines, str1 + r".*" + str2) self.assertRegex(without_new_lines, str3 + r".*" + str4) def test_answer_pool_2_multiplechoiceresponses_seed2(self): """Test two multiplechoiceresponses with different answer-pools and second seed.""" xml_str = textwrap.dedent( """

What is the correct answer?

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

Explanation

This is the 1st solution

Not much to explain here, sorry!

Explanation

This is the 2nd solution

What is the correct answer?

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

Explanation

This is the 1st solution

Not much to explain here, sorry!

Explanation

This is the 2nd solution

""" ) problem = new_loncapa_problem(xml_str, seed=9) the_html = problem.get_html() str1 = r"
.*\[.*'wrong-4'.*'wrong-3'.*'correct-1'.*\].*
" str2 = r"
.*\[.*'wrong-2'.*'wrong-3'.*'wrong-4'.*'correct-2'.*\].*
" str3 = r"
\{.*'1_solution_1'.*\}
" str4 = r"
\{.*'1_solution_4'.*\}
" self.assertRegex(the_html, str1) self.assertRegex(the_html, str2) self.assertRegex(the_html, str3) self.assertRegex(the_html, str4) without_new_lines = the_html.replace("\n", "") self.assertRegex(without_new_lines, str1 + r".*" + str2) self.assertRegex(without_new_lines, str3 + r".*" + str4) def test_answer_pool_random_consistent(self): """ The point of this test is to make sure that the exact randomization per seed does not change. """ xml_str = textwrap.dedent( """ wrong-1 wrong-2 correct-1 wrong-3 wrong-4 correct-2 correct-3 wrong-1 wrong-2 correct-1 wrong-3 wrong-4 correct-2 correct-3 wrong-1 wrong-2 correct-1 wrong-3 wrong-4 correct-2 correct-3 wrong-1 wrong-2 correct-1 wrong-3 wrong-4 correct-2 correct-3 """ ) problem = new_loncapa_problem(xml_str) the_html = problem.get_html() str1 = ( r"
.*\[.*'correct-2'.*'wrong-2'.*\].*
.*" + r"
.*\[.*'wrong-1'.*'correct-2'.*'wrong-4'.*\].*
.*" + r"
.*\[.*'correct-1'.*'wrong-4'.*\].*
.*" + r"
.*\[.*'wrong-1'.*'wrong-2'.*'correct-1'.*\].*
" ) without_new_lines = the_html.replace("\n", "") self.assertRegex(without_new_lines, str1) def test_no_answer_pool(self): """Test multiplechoiceresponse behavior when answer-pool attribute is missing.""" xml_str = textwrap.dedent( """

What is the correct answer?

wrong-1 wrong-2 correct-1 wrong-3 wrong-4
""" ) problem = new_loncapa_problem(xml_str, seed=723) the_html = problem.get_html() str1 = r"
.*\[.*'wrong-1'.*'wrong-2'.*'correct-1'.*'wrong-3'.*'wrong-4'.*\].*
" self.assertRegex(the_html, str1) # attributes *not* present response = list(problem.responders.values())[0] assert not response.has_mask() assert not response.has_answerpool() def test_answer_pool_and_no_answer_pool(self): """Test combination of responses with and without answer-pools.""" xml_str = textwrap.dedent( """

What is the correct answer?

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

Explanation

This is the solution

Not much to explain here, sorry!

What is the correct answer?

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

Explanation

This is the 1st solution

Not much to explain here, sorry!

Explanation

This is the 2nd solution

""" ) problem = new_loncapa_problem(xml_str, seed=723) the_html = problem.get_html() str1 = r"
.*\[.*'wrong-1'.*'wrong-2'.*'correct-1'.*'wrong-3'.*'wrong-4'.*\].*
" str2 = r"
.*\[.*'wrong-3'.*'correct-2'.*'wrong-2'.*'wrong-4'.*\].*
" str3 = r"
\{.*'1_solution_1'.*\}
" str4 = r"
\{.*'1_solution_3'.*\}
" self.assertRegex(the_html, str1) self.assertRegex(the_html, str2) self.assertRegex(the_html, str3) self.assertRegex(the_html, str4) without_new_lines = the_html.replace("\n", "") self.assertRegex(without_new_lines, str1 + r".*" + str2) self.assertRegex(without_new_lines, str3 + r".*" + str4) def test_answer_pool_without_solutionset(self): """Test answer-pool behavior when no solutionset is provided.""" xml_str = textwrap.dedent( """

What is the correct answer?

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

Explanation

This is the solution

Not much to explain here, sorry!

""" ) problem = new_loncapa_problem(xml_str, seed=723) the_html = problem.get_html() self.assertRegex(the_html, r"
.*\[.*'wrong-3'.*'correct-2'.*'wrong-2'.*'wrong-4'.*\].*
") self.assertRegex(the_html, r"
\{.*'1_solution_1'.*\}
")