Differences Between: [Versions 311 and 402]
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_ddwtos; 18 19 use question_answer; 20 use question_bank; 21 use question_hint_with_parts; 22 use question_possible_response; 23 24 defined('MOODLE_INTERNAL') || die(); 25 global $CFG; 26 27 require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); 28 require_once($CFG->dirroot . '/question/type/ddwtos/tests/helper.php'); 29 30 31 /** 32 * Unit tests for the drag-and-drop words into sentences question definition class. 33 * 34 * @package qtype_ddwtos 35 * @copyright 2012 The Open University 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 class question_type_test extends \question_testcase { 39 /** @var qtype_ddwtos instance of the question type class to test. */ 40 protected $qtype; 41 42 protected function setUp(): void { 43 $this->qtype = question_bank::get_qtype('ddwtos');; 44 } 45 46 protected function tearDown(): void { 47 $this->qtype = null; 48 } 49 50 public function assert_same_xml($expectedxml, $xml) { 51 $this->assertEquals(str_replace("\r\n", "\n", $expectedxml), 52 str_replace("\r\n", "\n", $xml)); 53 } 54 55 /** 56 * Get some test question data. 57 * 58 * @return object the data to construct a question like 59 * {@link qtype_ddwtos_test_helper::make_ddwtos_question_fox()}. 60 */ 61 protected function get_test_question_data() { 62 global $USER; 63 64 $dd = new \stdClass(); 65 $dd->id = 0; 66 $dd->category = 0; 67 $dd->contextid = 0; 68 $dd->parent = 0; 69 $dd->questiontextformat = FORMAT_HTML; 70 $dd->generalfeedbackformat = FORMAT_HTML; 71 $dd->defaultmark = 1; 72 $dd->penalty = 0.3333333; 73 $dd->length = 1; 74 $dd->stamp = make_unique_id_code(); 75 $dd->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY; 76 $dd->version = 1; 77 $dd->versionid = 0; 78 $dd->questionbankentryid = 0; 79 $dd->idnumber = null; 80 $dd->timecreated = time(); 81 $dd->timemodified = time(); 82 $dd->createdby = $USER->id; 83 $dd->modifiedby = $USER->id; 84 85 $dd->name = 'Drag-and-drop words into sentences question'; 86 $dd->questiontext = 'The [[1]] brown [[2]] jumped over the [[3]] dog.'; 87 $dd->generalfeedback = 'This sentence uses each letter of the alphabet.'; 88 $dd->qtype = 'ddwtos'; 89 90 $dd->options = new \stdClass(); 91 $dd->options->shuffleanswers = true; 92 93 \test_question_maker::set_standard_combined_feedback_fields($dd->options); 94 95 $dd->options->answers = array( 96 (object) array('answer' => 'quick', 'feedback' => 97 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;}'), 98 (object) array('answer' => 'fox', 'feedback' => 99 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;}'), 100 (object) array('answer' => 'lazy', 'feedback' => 101 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;}'), 102 (object) array('answer' => 'assiduous', 'feedback' => 103 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"3";s:8:"infinite";i:0;}'), 104 (object) array('answer' => 'dog', 'feedback' => 105 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"2";s:8:"infinite";i:0;}'), 106 (object) array('answer' => 'slow', 'feedback' => 107 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";i:0;}'), 108 ); 109 110 return $dd; 111 } 112 113 public function test_name() { 114 $this->assertEquals($this->qtype->name(), 'ddwtos'); 115 } 116 117 public function test_can_analyse_responses() { 118 $this->assertTrue($this->qtype->can_analyse_responses()); 119 } 120 121 public function test_save_question() { 122 $this->resetAfterTest(); 123 124 $syscontext = \context_system::instance(); 125 /** @var core_question_generator $generator */ 126 $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); 127 $category = $generator->create_question_category(['contextid' => $syscontext->id]); 128 129 $fromform = \test_question_maker::get_question_form_data('ddwtos', 'missingchoiceno'); 130 $fromform->category = $category->id . ',' . $syscontext->id; 131 132 $question = new \stdClass(); 133 $question->category = $category->id; 134 $question->qtype = 'ddwtos'; 135 $question->createdby = 0; 136 137 $this->qtype->save_question($question, $fromform); 138 $q = question_bank::load_question($question->id); 139 // We just want to verify that this does not cause errors, 140 // but also verify some of the outcome. 141 $this->assertEquals('The [[1]] sat on the [[2]].', $q->questiontext); 142 $this->assertEquals([1 => 1, 2 => 1], $q->places); 143 $this->assertEquals([1 => 1, 2 => 2], $q->rightchoices); 144 } 145 146 public function test_initialise_question_instance() { 147 $qdata = $this->get_test_question_data(); 148 149 $expected = \test_question_maker::make_question('ddwtos'); 150 $expected->stamp = $qdata->stamp; 151 $expected->idnumber = null; 152 153 $q = $this->qtype->make_question($qdata); 154 155 $this->assertEquals($expected, $q); 156 } 157 158 public function test_get_random_guess_score() { 159 $q = $this->get_test_question_data(); 160 $this->assertEqualsWithDelta(0.5, $this->qtype->get_random_guess_score($q), 0.0000001); 161 } 162 163 public function test_get_possible_responses() { 164 $q = $this->get_test_question_data(); 165 166 $this->assertEquals(array( 167 1 => array( 168 1 => new question_possible_response('quick', 1 / 3), 169 2 => new question_possible_response('slow', 0), 170 null => question_possible_response::no_response()), 171 2 => array( 172 1 => new question_possible_response('fox', 1 / 3), 173 2 => new question_possible_response('dog', 0), 174 null => question_possible_response::no_response()), 175 3 => array( 176 1 => new question_possible_response('lazy', 1 / 3), 177 2 => new question_possible_response('assiduous', 0), 178 null => question_possible_response::no_response()), 179 ), $this->qtype->get_possible_responses($q)); 180 } 181 182 public function test_xml_import() { 183 $xml = ' <question type="ddwtos"> 184 <name> 185 <text>A drag-and-drop question</text> 186 </name> 187 <questiontext format="moodle_auto_format"> 188 <text>Put these in order: [[1]], [[2]], [[3]].</text> 189 </questiontext> 190 <generalfeedback> 191 <text>The answer is Alpha, Beta, Gamma.</text> 192 </generalfeedback> 193 <defaultgrade>3</defaultgrade> 194 <penalty>0.3333333</penalty> 195 <hidden>0</hidden> 196 <shuffleanswers>1</shuffleanswers> 197 <correctfeedback> 198 <text><![CDATA[<p>Your answer is correct.</p>]]></text> 199 </correctfeedback> 200 <partiallycorrectfeedback> 201 <text><![CDATA[<p>Your answer is partially correct.</p>]]></text> 202 </partiallycorrectfeedback> 203 <incorrectfeedback> 204 <text><![CDATA[<p>Your answer is incorrect.</p>]]></text> 205 </incorrectfeedback> 206 <shownumcorrect/> 207 <dragbox> 208 <text>Alpha</text> 209 <group>1</group> 210 </dragbox> 211 <dragbox> 212 <text>Beta</text> 213 <group>1</group> 214 </dragbox> 215 <dragbox> 216 <text>Gamma</text> 217 <group>1</group> 218 <infinite/> 219 </dragbox> 220 <hint> 221 <text>Try again.</text> 222 <shownumcorrect /> 223 </hint> 224 <hint> 225 <text>These are the first three letters of the Greek alphabet.</text> 226 <shownumcorrect /> 227 <clearwrong /> 228 </hint> 229 </question>'; 230 $xmldata = xmlize($xml); 231 232 $importer = new \qformat_xml(); 233 $q = $importer->try_importing_using_qtypes( 234 $xmldata['question'], null, null, 'ddwtos'); 235 236 $expectedq = new \stdClass(); 237 $expectedq->qtype = 'ddwtos'; 238 $expectedq->name = 'A drag-and-drop question'; 239 $expectedq->questiontext = 'Put these in order: [[1]], [[2]], [[3]].'; 240 $expectedq->questiontextformat = FORMAT_MOODLE; 241 $expectedq->generalfeedback = 'The answer is Alpha, Beta, Gamma.'; 242 $expectedq->defaultmark = 3; 243 $expectedq->length = 1; 244 $expectedq->penalty = 0.3333333; 245 246 $expectedq->shuffleanswers = 1; 247 $expectedq->correctfeedback = array('text' => '<p>Your answer is correct.</p>', 248 'format' => FORMAT_MOODLE); 249 $expectedq->partiallycorrectfeedback = array( 250 'text' => '<p>Your answer is partially correct.</p>', 251 'format' => FORMAT_MOODLE); 252 $expectedq->shownumcorrect = true; 253 $expectedq->incorrectfeedback = array('text' => '<p>Your answer is incorrect.</p>', 254 'format' => FORMAT_MOODLE); 255 256 $expectedq->choices = array( 257 array('answer' => 'Alpha', 'choicegroup' => 1, 'infinite' => false), 258 array('answer' => 'Beta', 'choicegroup' => 1, 'infinite' => false), 259 array('answer' => 'Gamma', 'choicegroup' => 1, 'infinite' => true), 260 ); 261 262 $expectedq->hint = array( 263 array('text' => 'Try again.', 'format' => FORMAT_MOODLE), 264 array('text' => 'These are the first three letters of the Greek alphabet.', 265 'format' => FORMAT_MOODLE)); 266 $expectedq->hintshownumcorrect = array(true, true); 267 $expectedq->hintclearwrong = array(false, true); 268 269 $this->assert(new \question_check_specified_fields_expectation($expectedq), $q); 270 $this->assertEquals($expectedq->hint, $q->hint); 271 } 272 273 public function test_xml_export() { 274 $qdata = new \stdClass(); 275 $qdata->id = 123; 276 $qdata->contextid = \context_system::instance()->id; 277 $qdata->idnumber = null; 278 $qdata->qtype = 'ddwtos'; 279 $qdata->name = 'A drag-and-drop question'; 280 $qdata->questiontext = 'Put these in order: [[1]], [[2]], [[3]].'; 281 $qdata->questiontextformat = FORMAT_MOODLE; 282 $qdata->generalfeedback = 'The answer is Alpha, Beta, Gamma.'; 283 $qdata->generalfeedbackformat = FORMAT_MOODLE; 284 $qdata->defaultmark = 3; 285 $qdata->length = 1; 286 $qdata->penalty = 0.3333333; 287 $qdata->status = \core_question\local\bank\question_version_status::QUESTION_STATUS_READY; 288 289 $qdata->options = new \stdClass(); 290 $qdata->options->shuffleanswers = 1; 291 $qdata->options->correctfeedback = '<p>Your answer is correct.</p>'; 292 $qdata->options->correctfeedbackformat = FORMAT_MOODLE; 293 $qdata->options->partiallycorrectfeedback = '<p>Your answer is partially correct.</p>'; 294 $qdata->options->partiallycorrectfeedbackformat = FORMAT_MOODLE; 295 $qdata->options->shownumcorrect = 1; 296 $qdata->options->incorrectfeedback = '<p>Your answer is incorrect.</p>'; 297 $qdata->options->incorrectfeedbackformat = FORMAT_MOODLE; 298 299 $qdata->options->answers = array( 300 13 => new question_answer(13, 'Alpha', 0, 301 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}', 302 FORMAT_MOODLE), 303 14 => new question_answer(14, 'Beta', 0, 304 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:0;}', 305 FORMAT_MOODLE), 306 15 => new question_answer(15, 'Gamma', 0, 307 'O:8:"stdClass":2:{s:9:"draggroup";s:1:"1";s:8:"infinite";b:1;}', 308 FORMAT_MOODLE), 309 ); 310 311 $qdata->hints = array( 312 1 => new question_hint_with_parts(1, 'Try again.', FORMAT_MOODLE, true, false), 313 2 => new question_hint_with_parts(2, 314 'These are the first three letters of the Greek alphabet.', 315 FORMAT_MOODLE, true, true), 316 ); 317 318 $exporter = new \qformat_xml(); 319 $xml = $exporter->writequestion($qdata); 320 321 $expectedxml = '<!-- question: 123 --> 322 <question type="ddwtos"> 323 <name> 324 <text>A drag-and-drop question</text> 325 </name> 326 <questiontext format="moodle_auto_format"> 327 <text>Put these in order: [[1]], [[2]], [[3]].</text> 328 </questiontext> 329 <generalfeedback format="moodle_auto_format"> 330 <text>The answer is Alpha, Beta, Gamma.</text> 331 </generalfeedback> 332 <defaultgrade>3</defaultgrade> 333 <penalty>0.3333333</penalty> 334 <hidden>0</hidden> 335 <idnumber></idnumber> 336 <shuffleanswers>1</shuffleanswers> 337 <correctfeedback format="moodle_auto_format"> 338 <text><![CDATA[<p>Your answer is correct.</p>]]></text> 339 </correctfeedback> 340 <partiallycorrectfeedback format="moodle_auto_format"> 341 <text><![CDATA[<p>Your answer is partially correct.</p>]]></text> 342 </partiallycorrectfeedback> 343 <incorrectfeedback format="moodle_auto_format"> 344 <text><![CDATA[<p>Your answer is incorrect.</p>]]></text> 345 </incorrectfeedback> 346 <shownumcorrect/> 347 <dragbox> 348 <text>Alpha</text> 349 <group>1</group> 350 </dragbox> 351 <dragbox> 352 <text>Beta</text> 353 <group>1</group> 354 </dragbox> 355 <dragbox> 356 <text>Gamma</text> 357 <group>1</group> 358 <infinite/> 359 </dragbox> 360 <hint format="moodle_auto_format"> 361 <text>Try again.</text> 362 <shownumcorrect/> 363 </hint> 364 <hint format="moodle_auto_format"> 365 <text>These are the first three letters of the Greek alphabet.</text> 366 <shownumcorrect/> 367 <clearwrong/> 368 </hint> 369 </question> 370 '; 371 372 $this->assert_same_xml($expectedxml, $xml); 373 } 374 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body