See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace qtype_multichoice; 18 19 use question_state; 20 21 defined('MOODLE_INTERNAL') || die(); 22 23 global $CFG; 24 require_once($CFG->dirroot . '/question/engine/lib.php'); 25 require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); 26 27 28 /** 29 * Unit tests for the mutiple choice question type. 30 * 31 * Note, there are already lots of tests of the multichoice type in the behaviour 32 * tests. (Search for \test_question_maker::make_a_multichoice.) This file only 33 * contains a few additional tests for problems that were found during testing. 34 * 35 * @package qtype_multichoice 36 * @copyright 2010 The Open University 37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 38 * @covers \qtype_multichoice_single_question 39 * @covers \qtype_multichoice_single_base 40 */ 41 class walkthrough_test extends \qbehaviour_walkthrough_test_base { 42 public function test_deferredfeedback_feedback_multichoice_single() { 43 44 // Create a multichoice, single question. 45 $mc = \test_question_maker::make_a_multichoice_single_question(); 46 $mc->shuffleanswers = false; 47 $mc->answers[14]->fraction = 0.1; // Make one of the choices partially right. 48 $rightindex = 0; 49 50 $this->start_attempt_at_question($mc, 'deferredfeedback', 3); 51 $this->process_submission(array('answer' => $rightindex)); 52 53 // Verify. 54 $this->check_current_state(question_state::$complete); 55 $this->check_current_mark(null); 56 $this->check_current_output( 57 $this->get_contains_mc_radio_expectation($rightindex, true, true), 58 $this->get_contains_mc_radio_expectation($rightindex + 1, true, false), 59 $this->get_contains_mc_radio_expectation($rightindex + 2, true, false), 60 $this->get_does_not_contain_correctness_expectation(), 61 $this->get_does_not_contain_feedback_expectation()); 62 63 // Finish the attempt. 64 $this->quba->finish_all_questions(); 65 66 // Verify. 67 $this->check_current_state(question_state::$gradedright); 68 $this->check_current_mark(3); 69 $this->check_current_output( 70 $this->get_contains_mc_radio_expectation($rightindex, false, true), 71 $this->get_contains_correct_expectation(), 72 new \question_pattern_expectation('/class="r0 correct"/'), 73 new \question_pattern_expectation('/class="r1"/')); 74 75 // Regrade with a new version of the question. 76 $oldmc = \test_question_maker::make_a_multichoice_single_question(); 77 $oldmc->answers = [ 78 23 => $oldmc->answers[13], 79 24 => $oldmc->answers[14], 80 25 => $oldmc->answers[15], 81 ]; 82 $oldmc->answers[23]->fraction = 0.5; 83 $oldmc->answers[23]->feedback = 'A is now only partially right'; 84 $oldmc->answers[24]->fraction = 1; 85 $oldmc->answers[24]->answer = 'B is the new right answer'; 86 $this->quba->regrade_question($this->slot, true, null, $oldmc); 87 88 // Verify. 89 $this->check_current_mark(1.5); 90 $this->render(); 91 $this->assertStringContainsString('A is now only partially right', $this->currentoutput); 92 $this->assertStringContainsString('B is the new right answer', $this->currentoutput); 93 $this->assertStringNotContainsString( 94 get_string('deletedchoice', 'qtype_multichoice'), $this->currentoutput); 95 } 96 97 public function test_deferredfeedback_feedback_multichoice_single_showstandardunstruction_yes() { 98 99 // Create a multichoice, single question. 100 $mc = \test_question_maker::make_a_multichoice_single_question(); 101 $mc->showstandardinstruction = true; 102 103 $this->start_attempt_at_question($mc, 'deferredfeedback', 3); 104 $this->render(); 105 106 // Check for 'Show standard instruction'. 107 $standardinstruction = get_string('selectone', 'qtype_multichoice'); 108 $this->assertStringContainsString($standardinstruction, $this->currentoutput); 109 } 110 111 public function test_deferredfeedback_feedback_multichoice_single_showstandardunstruction_no() { 112 113 // Create a multichoice, single question. 114 $mc = \test_question_maker::make_a_multichoice_single_question(); 115 $mc->showstandardinstruction = false; 116 117 $this->start_attempt_at_question($mc, 'deferredfeedback', 3); 118 $this->render(); 119 120 // Check for 'Show standard instruction'. 121 $standardinstruction = get_string('selectmulti', 'qtype_multichoice'); 122 $this->assertStringNotContainsString($standardinstruction, $this->currentoutput); 123 } 124 125 public function test_deferredfeedback_feedback_multichoice_multi() { 126 // Create a multichoice, multi question. 127 $mc = \test_question_maker::make_a_multichoice_multi_question(); 128 $mc->shuffleanswers = false; 129 130 $this->start_attempt_at_question($mc, 'deferredfeedback', 2); 131 $this->process_submission($mc->get_correct_response()); 132 $this->quba->finish_all_questions(); 133 134 // Verify. 135 $this->check_current_state(question_state::$gradedright); 136 $this->check_current_mark(2); 137 $this->check_current_output( 138 $this->get_contains_mc_checkbox_expectation('choice0', false, true), 139 $this->get_contains_mc_checkbox_expectation('choice1', false, false), 140 $this->get_contains_mc_checkbox_expectation('choice2', false, true), 141 $this->get_contains_mc_checkbox_expectation('choice3', false, false), 142 $this->get_contains_correct_expectation(), 143 new \question_pattern_expectation('/class="r0 correct"/'), 144 new \question_pattern_expectation('/class="r1"/')); 145 } 146 147 /** 148 * Test for clear choice option. 149 */ 150 public function test_deferredfeedback_feedback_multichoice_clearchoice() { 151 152 // Create a multichoice, single question. 153 $mc = \test_question_maker::make_a_multichoice_single_question(); 154 $mc->shuffleanswers = false; 155 156 $clearchoice = -1; 157 $rightchoice = 0; 158 $wrongchoice = 2; 159 160 $this->start_attempt_at_question($mc, 'deferredfeedback', 3); 161 162 // Let's first submit the wrong choice (2). 163 $this->process_submission(array('answer' => $wrongchoice)); // Wrong choice (2). 164 165 $this->check_current_mark(null); 166 // Clear choice radio should not be checked. 167 $this->check_current_output( 168 $this->get_contains_mc_radio_expectation($rightchoice, true, false), // Not checked. 169 $this->get_contains_mc_radio_expectation($rightchoice + 1, true, false), // Not checked. 170 $this->get_contains_mc_radio_expectation($rightchoice + 2, true, true), // Wrong choice (2) checked. 171 $this->get_contains_mc_radio_expectation($clearchoice, true, false), // Not checked. 172 $this->get_does_not_contain_correctness_expectation(), 173 $this->get_does_not_contain_feedback_expectation() 174 ); 175 176 // Now, let's clear our previous choice. 177 $this->process_submission(array('answer' => $clearchoice)); // Clear choice (-1). 178 $this->check_current_mark(null); 179 180 // This time, the clear choice radio should be the only one checked. 181 $this->check_current_output( 182 $this->get_contains_mc_radio_expectation($rightchoice, true, false), // Not checked. 183 $this->get_contains_mc_radio_expectation($rightchoice + 1, true, false), // Not checked. 184 $this->get_contains_mc_radio_expectation($rightchoice + 2, true, false), // Not checked. 185 $this->get_contains_mc_radio_expectation($clearchoice, true, true), // Clear choice radio checked. 186 $this->get_does_not_contain_correctness_expectation(), 187 $this->get_does_not_contain_feedback_expectation() 188 ); 189 190 // Finally, let's submit the right choice. 191 $this->process_submission(array('answer' => $rightchoice)); // Right choice (0). 192 $this->check_current_state(question_state::$complete); 193 $this->check_current_mark(null); 194 $this->check_current_output( 195 $this->get_contains_mc_radio_expectation($rightchoice, true, true), 196 $this->get_contains_mc_radio_expectation($rightchoice + 1, true, false), 197 $this->get_contains_mc_radio_expectation($rightchoice + 2, true, false), 198 $this->get_contains_mc_radio_expectation($clearchoice, true, false), 199 $this->get_does_not_contain_correctness_expectation(), 200 $this->get_does_not_contain_feedback_expectation() 201 ); 202 203 // Finish the attempt. 204 $this->finish(); 205 206 // Verify. 207 $this->check_current_state(question_state::$gradedright); 208 $this->check_current_mark(3); 209 $this->check_current_output( 210 $this->get_contains_mc_radio_expectation($rightchoice, false, true), 211 $this->get_contains_correct_expectation(), 212 new \question_pattern_expectation('/class="r0 correct"/'), 213 new \question_pattern_expectation('/class="r1"/')); 214 } 215 216 public function test_each_attempt_builds_on_last_and_regrade() { 217 218 // Create a multichoice, single question. 219 $mc = \test_question_maker::make_a_multichoice_single_question(); 220 $mc->shuffleanswers = false; 221 222 $rightchoice = 0; 223 224 $this->start_attempt_at_question(clone($mc), 'deferredfeedback', 3); 225 226 // Submit the answer false (correct). 227 $this->process_submission(['answer' => $rightchoice]); 228 229 // Finish the attempt. 230 $this->quba->finish_all_questions(); 231 232 // Check the state. 233 $this->check_current_state(question_state::$gradedright); 234 $this->check_current_mark(3); 235 $this->check_current_output( 236 $this->get_contains_mc_radio_expectation($rightchoice, false, true), 237 $this->get_contains_mc_radio_expectation($rightchoice + 1, false, false), 238 $this->get_contains_mc_radio_expectation($rightchoice + 2, false, false)); 239 240 // Start a new attempt based on the first one. 241 $firstattemptqa = $this->quba->get_question_attempt($this->slot); 242 $this->quba = \question_engine::make_questions_usage_by_activity('unit_test', 243 \context_system::instance()); 244 $this->quba->set_preferred_behaviour('deferredfeedback'); 245 $this->slot = $this->quba->add_question(clone($mc), 3); 246 $this->quba->start_question_based_on($this->slot, $firstattemptqa); 247 248 // Verify. 249 $this->check_current_state(question_state::$complete); 250 $this->check_current_mark(null); 251 $this->check_current_output( 252 $this->get_contains_mc_radio_expectation($rightchoice, true, true), 253 $this->get_contains_mc_radio_expectation($rightchoice + 1, true, false), 254 $this->get_contains_mc_radio_expectation($rightchoice + 2, true, false)); 255 256 // Finish the attempt without changing the answer. 257 $this->quba->finish_all_questions(); 258 259 // Check the state. 260 $this->check_current_state(question_state::$gradedright); 261 $this->check_current_mark(3); 262 $this->check_current_output( 263 $this->get_contains_mc_radio_expectation($rightchoice, false, true), 264 $this->get_contains_mc_radio_expectation($rightchoice + 1, false, false), 265 $this->get_contains_mc_radio_expectation($rightchoice + 2, false, false)); 266 267 // Regrade the attempt - code based on question_usage_by_activity::regrade_question. 268 $oldqa = $this->quba->get_question_attempt($this->slot); 269 $newqa = new \question_attempt(clone($mc), 270 $oldqa->get_usage_id(), $this->quba->get_observer()); 271 $newqa->set_database_id($oldqa->get_database_id()); 272 $newqa->set_slot($oldqa->get_slot()); 273 $newqa->set_max_mark(3); 274 $newqa->regrade($oldqa, true); 275 276 // Check the state. 277 $this->assertEquals(question_state::$gradedright, $newqa->get_state()); 278 $this->assertEquals(3, $newqa->get_mark()); 279 } 280 281 public function test_deferredfeedback_feedback_multichoice_multi_showstandardunstruction_yes() { 282 283 // Create a multichoice, multi question. 284 $mc = \test_question_maker::make_a_multichoice_multi_question(); 285 $mc->showstandardinstruction = true; 286 287 $this->start_attempt_at_question($mc, 'deferredfeedback', 3); 288 $this->render(); 289 290 // Check for 'Show standard instruction'. 291 $standardinstruction = get_string('selectmulti', 'qtype_multichoice'); 292 $this->assertStringContainsString($standardinstruction, $this->currentoutput); 293 } 294 295 public function test_deferredfeedback_feedback_multichoice_multi_showstandardunstruction_no() { 296 297 // Create a multichoice, multi question. 298 $mc = \test_question_maker::make_a_multichoice_multi_question(); 299 $mc->showstandardinstruction = false; 300 301 $this->start_attempt_at_question($mc, 'deferredfeedback', 3); 302 $this->render(); 303 304 // Check for 'Show standard instruction'. 305 $standardinstruction = \html_writer::tag('legend', get_string('answer'), [ 306 'class' => 'prompt h6 font-weight-normal sr-only' 307 ]); 308 $this->assertStringContainsString($standardinstruction, $this->currentoutput); 309 } 310 311 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body