See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 401 and 402] [Versions 401 and 403]
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_match; 18 19 use question_attempt_step; 20 use question_classified_response; 21 use question_display_options; 22 use question_state; 23 24 defined('MOODLE_INTERNAL') || die(); 25 26 global $CFG; 27 require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); 28 29 30 /** 31 * Unit tests for the matching question definition class. 32 * 33 * @package qtype_match 34 * @copyright 2009 The Open University 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 * @covers \qtype_match_question 37 */ 38 class question_test extends \advanced_testcase { 39 40 public function test_get_expected_data() { 41 $question = \test_question_maker::make_question('match'); 42 $question->start_attempt(new question_attempt_step(), 1); 43 44 $this->assertEquals(array('sub0' => PARAM_INT, 'sub1' => PARAM_INT, 45 'sub2' => PARAM_INT, 'sub3' => PARAM_INT), $question->get_expected_data()); 46 } 47 48 public function test_is_complete_response() { 49 $question = \test_question_maker::make_question('match'); 50 $question->start_attempt(new question_attempt_step(), 1); 51 52 $this->assertFalse($question->is_complete_response(array())); 53 $this->assertFalse($question->is_complete_response( 54 array('sub0' => '1', 'sub1' => '1', 'sub2' => '1', 'sub3' => '0'))); 55 $this->assertFalse($question->is_complete_response(array('sub1' => '1'))); 56 $this->assertTrue($question->is_complete_response( 57 array('sub0' => '1', 'sub1' => '1', 'sub2' => '1', 'sub3' => '1'))); 58 } 59 60 public function test_is_gradable_response() { 61 $question = \test_question_maker::make_question('match'); 62 $question->start_attempt(new question_attempt_step(), 1); 63 64 $this->assertFalse($question->is_gradable_response(array())); 65 $this->assertFalse($question->is_gradable_response( 66 array('sub0' => '0', 'sub1' => '0', 'sub2' => '0', 'sub3' => '0'))); 67 $this->assertTrue($question->is_gradable_response( 68 array('sub0' => '1', 'sub1' => '0', 'sub2' => '0', 'sub3' => '0'))); 69 $this->assertTrue($question->is_gradable_response(array('sub1' => '1'))); 70 $this->assertTrue($question->is_gradable_response( 71 array('sub0' => '1', 'sub1' => '1', 'sub2' => '3', 'sub3' => '1'))); 72 } 73 74 public function test_is_same_response() { 75 $question = \test_question_maker::make_question('match'); 76 $question->start_attempt(new question_attempt_step(), 1); 77 78 $this->assertTrue($question->is_same_response( 79 array(), 80 array('sub0' => '0', 'sub1' => '0', 'sub2' => '0', 'sub3' => '0'))); 81 82 $this->assertTrue($question->is_same_response( 83 array('sub0' => '0', 'sub1' => '0', 'sub2' => '0', 'sub3' => '0'), 84 array('sub0' => '0', 'sub1' => '0', 'sub2' => '0', 'sub3' => '0'))); 85 86 $this->assertFalse($question->is_same_response( 87 array('sub0' => '0', 'sub1' => '0', 'sub2' => '0', 'sub3' => '0'), 88 array('sub0' => '1', 'sub1' => '2', 'sub2' => '3', 'sub3' => '1'))); 89 90 $this->assertTrue($question->is_same_response( 91 array('sub0' => '1', 'sub1' => '2', 'sub2' => '3', 'sub3' => '1'), 92 array('sub0' => '1', 'sub1' => '2', 'sub2' => '3', 'sub3' => '1'))); 93 94 $this->assertFalse($question->is_same_response( 95 array('sub0' => '2', 'sub1' => '2', 'sub2' => '3', 'sub3' => '1'), 96 array('sub0' => '1', 'sub1' => '2', 'sub2' => '3', 'sub3' => '1'))); 97 } 98 99 public function test_grading() { 100 $question = \test_question_maker::make_question('match'); 101 $question->start_attempt(new question_attempt_step(), 1); 102 103 $correctresponse = $question->prepare_simulated_post_data( 104 array('Dog' => 'Mammal', 105 'Frog' => 'Amphibian', 106 'Toad' => 'Amphibian', 107 'Cat' => 'Mammal')); 108 $this->assertEquals(array(1, question_state::$gradedright), $question->grade_response($correctresponse)); 109 110 $partialresponse = $question->prepare_simulated_post_data(array('Dog' => 'Mammal')); 111 $this->assertEquals(array(0.25, question_state::$gradedpartial), $question->grade_response($partialresponse)); 112 113 $partiallycorrectresponse = $question->prepare_simulated_post_data( 114 array('Dog' => 'Mammal', 115 'Frog' => 'Insect', 116 'Toad' => 'Insect', 117 'Cat' => 'Amphibian')); 118 $this->assertEquals(array(0.25, question_state::$gradedpartial), $question->grade_response($partiallycorrectresponse)); 119 120 $wrongresponse = $question->prepare_simulated_post_data( 121 array('Dog' => 'Amphibian', 122 'Frog' => 'Insect', 123 'Toad' => 'Insect', 124 'Cat' => 'Amphibian')); 125 $this->assertEquals(array(0, question_state::$gradedwrong), $question->grade_response($wrongresponse)); 126 } 127 128 public function test_get_correct_response() { 129 $question = \test_question_maker::make_question('match'); 130 $question->start_attempt(new question_attempt_step(), 1); 131 132 $correct = $question->prepare_simulated_post_data(array('Dog' => 'Mammal', 133 'Frog' => 'Amphibian', 134 'Toad' => 'Amphibian', 135 'Cat' => 'Mammal')); 136 $this->assertEquals($correct, $question->get_correct_response()); 137 } 138 139 public function test_get_question_summary() { 140 $match = \test_question_maker::make_question('match'); 141 $match->start_attempt(new question_attempt_step(), 1); 142 $qsummary = $match->get_question_summary(); 143 $this->assertMatchesRegularExpression('/' . preg_quote($match->questiontext, '/') . '/', $qsummary); 144 foreach ($match->stems as $stem) { 145 $this->assertMatchesRegularExpression('/' . preg_quote($stem, '/') . '/', $qsummary); 146 } 147 foreach ($match->choices as $choice) { 148 $this->assertMatchesRegularExpression('/' . preg_quote($choice, '/') . '/', $qsummary); 149 } 150 } 151 152 public function test_summarise_response() { 153 $match = \test_question_maker::make_question('match'); 154 $match->start_attempt(new question_attempt_step(), 1); 155 156 $summary = $match->summarise_response($match->prepare_simulated_post_data(array('Dog' => 'Amphibian', 'Frog' => 'Mammal'))); 157 158 $this->assertMatchesRegularExpression('/Dog -> Amphibian/', $summary); 159 $this->assertMatchesRegularExpression('/Frog -> Mammal/', $summary); 160 } 161 162 public function test_classify_response() { 163 $match = \test_question_maker::make_question('match'); 164 $match->start_attempt(new question_attempt_step(), 1); 165 166 $response = $match->prepare_simulated_post_data(array('Dog' => 'Amphibian', 'Frog' => 'Insect', 'Toad' => '', 'Cat' => '')); 167 $this->assertEquals(array( 168 1 => new question_classified_response(2, 'Amphibian', 0), 169 2 => new question_classified_response(3, 'Insect', 0), 170 3 => question_classified_response::no_response(), 171 4 => question_classified_response::no_response(), 172 ), $match->classify_response($response)); 173 174 $response = $match->prepare_simulated_post_data(array('Dog' => 'Mammal', 'Frog' => 'Amphibian', 175 'Toad' => 'Amphibian', 'Cat' => 'Mammal')); 176 $this->assertEquals(array( 177 1 => new question_classified_response(1, 'Mammal', 0.25), 178 2 => new question_classified_response(2, 'Amphibian', 0.25), 179 3 => new question_classified_response(2, 'Amphibian', 0.25), 180 4 => new question_classified_response(1, 'Mammal', 0.25), 181 ), $match->classify_response($response)); 182 } 183 184 public function test_classify_response_choice_deleted_after_attempt() { 185 $match = \test_question_maker::make_question('match'); 186 $firststep = new question_attempt_step(); 187 188 $match->start_attempt($firststep, 1); 189 $response = $match->prepare_simulated_post_data(array( 190 'Dog' => 'Amphibian', 'Frog' => 'Insect', 'Toad' => '', 'Cat' => 'Mammal')); 191 192 $match = \test_question_maker::make_question('match'); 193 unset($match->stems[4]); 194 unset($match->stemsformat[4]); 195 unset($match->right[4]); 196 $match->apply_attempt_state($firststep); 197 198 $this->assertEquals(array( 199 1 => new question_classified_response(2, 'Amphibian', 0), 200 2 => new question_classified_response(3, 'Insect', 0), 201 3 => question_classified_response::no_response(), 202 ), $match->classify_response($response)); 203 } 204 205 public function test_classify_response_choice_added_after_attempt() { 206 $match = \test_question_maker::make_question('match'); 207 $firststep = new question_attempt_step(); 208 209 $match->start_attempt($firststep, 1); 210 $response = $match->prepare_simulated_post_data(array( 211 'Dog' => 'Amphibian', 'Frog' => 'Insect', 'Toad' => '', 'Cat' => 'Mammal')); 212 213 $match = \test_question_maker::make_question('match'); 214 $match->stems[5] = "Snake"; 215 $match->stemsformat[5] = FORMAT_HTML; 216 $match->choices[5] = "Reptile"; 217 $match->right[5] = 5; 218 $match->apply_attempt_state($firststep); 219 220 $this->assertEquals(array( 221 1 => new question_classified_response(2, 'Amphibian', 0), 222 2 => new question_classified_response(3, 'Insect', 0), 223 3 => question_classified_response::no_response(), 224 4 => new question_classified_response(1, 'Mammal', 0.20), 225 ), $match->classify_response($response)); 226 } 227 228 public function test_prepare_simulated_post_data() { 229 $m = \test_question_maker::make_question('match'); 230 $m->start_attempt(new question_attempt_step(), 1); 231 $postdata = $m->prepare_simulated_post_data(array('Dog' => 'Mammal', 'Frog' => 'Amphibian', 232 'Toad' => 'Amphibian', 'Cat' => 'Mammal')); 233 $this->assertEquals(array(4, 4), $m->get_num_parts_right($postdata)); 234 } 235 236 /** 237 * test_get_question_definition_for_external_rendering 238 */ 239 public function test_get_question_definition_for_external_rendering() { 240 $question = \test_question_maker::make_question('match'); 241 $question->start_attempt(new question_attempt_step(), 1); 242 $qa = \test_question_maker::get_a_qa($question); 243 $displayoptions = new question_display_options(); 244 245 $options = $question->get_question_definition_for_external_rendering($qa, $displayoptions); 246 $this->assertEquals(1, $options['shufflestems']); 247 } 248 249 public function test_validate_can_regrade_with_other_version_ok() { 250 $m = \test_question_maker::make_question('match'); 251 252 $newm = clone($m); 253 254 $this->assertNull($newm->validate_can_regrade_with_other_version($m)); 255 } 256 257 public function test_validate_can_regrade_with_other_version_bad_stems() { 258 $m = \test_question_maker::make_question('match'); 259 260 $newm = clone($m); 261 unset($newm->stems[4]); 262 263 $this->assertEquals(get_string('regradeissuenumstemschanged', 'qtype_match'), 264 $newm->validate_can_regrade_with_other_version($m)); 265 } 266 267 public function test_validate_can_regrade_with_other_version_bad_choices() { 268 $m = \test_question_maker::make_question('match'); 269 270 $newm = clone($m); 271 unset($newm->choices[3]); 272 273 $this->assertEquals(get_string('regradeissuenumchoiceschanged', 'qtype_match'), 274 $newm->validate_can_regrade_with_other_version($m)); 275 } 276 277 public function test_update_attempt_state_date_from_old_version_bad() { 278 $m = \test_question_maker::make_question('match'); 279 280 $newm = clone($m); 281 $newm->stems = [11 => 'Dog', 12 => 'Frog', 13 => 'Toad', 14 => 'Cat', 15 => 'Hippopotamus']; 282 $newm->stemformat = [11 => FORMAT_HTML, 12 => FORMAT_HTML, 13 => FORMAT_HTML, 14 => FORMAT_HTML, 15 => FORMAT_HTML]; 283 $newm->choices = [11 => 'Mammal', 12 => 'Amphibian', 13 => 'Insect']; 284 $newm->right = [11 => 11, 12 => 12, 13 => 12, 14 => 11, 15 => 11]; 285 286 $oldstep = new question_attempt_step(); 287 $oldstep->set_qt_var('_stemorder', '4,1,3,2'); 288 $oldstep->set_qt_var('_choiceorder', '2,3,1'); 289 $this->expectExceptionMessage(get_string('regradeissuenumstemschanged', 'qtype_match')); 290 $newm->update_attempt_state_data_for_new_version($oldstep, $m); 291 } 292 293 public function test_update_attempt_state_date_from_old_version_ok() { 294 $m = \test_question_maker::make_question('match'); 295 296 $newm = clone($m); 297 $newm->stems = [11 => 'Dog', 12 => 'Frog', 13 => 'Toad', 14 => 'Cat']; 298 $newm->stemformat = [11 => FORMAT_HTML, 12 => FORMAT_HTML, 13 => FORMAT_HTML, 14 => FORMAT_HTML]; 299 $newm->choices = [11 => 'Mammal', 12 => 'Amphibian', 13 => 'Insect']; 300 $newm->right = [11 => 11, 12 => 12, 13 => 12, 14 => 11]; 301 302 $oldstep = new question_attempt_step(); 303 $oldstep->set_qt_var('_stemorder', '4,1,3,2'); 304 $oldstep->set_qt_var('_choiceorder', '2,3,1'); 305 $this->assertEquals(['_stemorder' => '14,11,13,12', '_choiceorder' => '12,13,11'], 306 $newm->update_attempt_state_data_for_new_version($oldstep, $m)); 307 } 308 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body