Differences Between: [Versions 311 and 400] [Versions 400 and 401] [Versions 400 and 402] [Versions 400 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_multichoice; 18 19 use qtype_multichoice; 20 use qtype_multichoice_edit_form; 21 use question_possible_response; 22 23 defined('MOODLE_INTERNAL') || die(); 24 25 global $CFG; 26 require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); 27 require_once($CFG->dirroot . '/question/type/multichoice/questiontype.php'); 28 require_once($CFG->dirroot . '/question/type/edit_question_form.php'); 29 require_once($CFG->dirroot . '/question/type/multichoice/edit_multichoice_form.php'); 30 31 /** 32 * Unit tests for the multiple choice question definition class. 33 * 34 * @package qtype_multichoice 35 * @copyright 2009 The Open University 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 class question_type_test extends \advanced_testcase { 39 protected $qtype; 40 41 protected function setUp(): void { 42 $this->qtype = new qtype_multichoice(); 43 } 44 45 protected function tearDown(): void { 46 $this->qtype = null; 47 } 48 49 public function test_name() { 50 $this->assertEquals($this->qtype->name(), 'multichoice'); 51 } 52 53 protected function get_test_question_data() { 54 $q = new \stdClass(); 55 $q->id = 1; 56 $q->options = new \stdClass(); 57 $q->options->single = true; 58 $q->options->answers[1] = (object) array('answer' => 'frog', 59 'answerformat' => FORMAT_HTML, 'fraction' => 1); 60 $q->options->answers[2] = (object) array('answer' => 'toad', 61 'answerformat' => FORMAT_HTML, 'fraction' => 0); 62 63 return $q; 64 } 65 66 public function test_can_analyse_responses() { 67 $this->assertTrue($this->qtype->can_analyse_responses()); 68 } 69 70 public function test_get_random_guess_score() { 71 $q = $this->get_test_question_data(); 72 $this->assertEquals(0.5, $this->qtype->get_random_guess_score($q)); 73 } 74 75 public function test_get_random_guess_score_multi() { 76 $q = $this->get_test_question_data(); 77 $q->options->single = false; 78 $this->assertNull($this->qtype->get_random_guess_score($q)); 79 } 80 81 public function test_get_possible_responses_single() { 82 $q = $this->get_test_question_data(); 83 $responses = $this->qtype->get_possible_responses($q); 84 85 $this->assertEquals(array( 86 $q->id => array( 87 1 => new question_possible_response('frog', 1), 88 2 => new question_possible_response('toad', 0), 89 null => question_possible_response::no_response(), 90 )), $this->qtype->get_possible_responses($q)); 91 } 92 93 public function test_get_possible_responses_multi() { 94 $q = $this->get_test_question_data(); 95 $q->options->single = false; 96 97 $this->assertEquals(array( 98 1 => array(1 => new question_possible_response('frog', 1)), 99 2 => array(2 => new question_possible_response('toad', 0)), 100 ), $this->qtype->get_possible_responses($q)); 101 } 102 103 public function get_question_saving_which() { 104 return array(array('two_of_four'), array('one_of_four')); 105 } 106 107 /** 108 * @dataProvider get_question_saving_which 109 */ 110 public function test_question_saving_two_of_four($which) { 111 $this->resetAfterTest(true); 112 $this->setAdminUser(); 113 114 $questiondata = \test_question_maker::get_question_data('multichoice', $which); 115 $formdata = \test_question_maker::get_question_form_data('multichoice', $which); 116 117 $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); 118 $cat = $generator->create_question_category(array()); 119 120 $formdata->category = "{$cat->id},{$cat->contextid}"; 121 qtype_multichoice_edit_form::mock_submit((array)$formdata); 122 123 $form = \qtype_multichoice_test_helper::get_question_editing_form($cat, $questiondata); 124 125 $this->assertTrue($form->is_validated()); 126 127 $fromform = $form->get_data(); 128 129 $returnedfromsave = $this->qtype->save_question($questiondata, $fromform); 130 $actualquestionsdata = question_load_questions([$returnedfromsave->id], 'qbe.idnumber'); 131 $actualquestiondata = end($actualquestionsdata); 132 133 foreach ($questiondata as $property => $value) { 134 if (!in_array($property, ['id', 'timemodified', 'timecreated', 'options', 'hints', 'stamp', 135 'versionid', 'questionbankentryid'])) { 136 $this->assertEquals($value, $actualquestiondata->$property); 137 } 138 } 139 140 foreach ($questiondata->options as $optionname => $value) { 141 if ($optionname != 'answers') { 142 $this->assertEquals($value, $actualquestiondata->options->$optionname); 143 } 144 } 145 146 foreach ($questiondata->hints as $hint) { 147 $actualhint = array_shift($actualquestiondata->hints); 148 foreach ($hint as $property => $value) { 149 if (!in_array($property, array('id', 'questionid', 'options'))) { 150 $this->assertEquals($value, $actualhint->$property); 151 } 152 } 153 } 154 155 foreach ($questiondata->options->answers as $answer) { 156 $actualanswer = array_shift($actualquestiondata->options->answers); 157 foreach ($answer as $ansproperty => $ansvalue) { 158 // This question does not use 'answerformat', will ignore it. 159 if (!in_array($ansproperty, array('id', 'question', 'answerformat'))) { 160 $this->assertEquals($ansvalue, $actualanswer->$ansproperty); 161 } 162 } 163 } 164 } 165 166 /** 167 * Test to make sure that loading of question options works, including in an error case. 168 */ 169 public function test_get_question_options() { 170 global $DB; 171 172 $this->resetAfterTest(true); 173 $this->setAdminUser(); 174 175 // Create a complete, in DB question to use. 176 $questiondata = \test_question_maker::get_question_data('multichoice', 'two_of_four'); 177 $formdata = \test_question_maker::get_question_form_data('multichoice', 'two_of_four'); 178 179 $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); 180 $cat = $generator->create_question_category(array()); 181 182 $formdata->category = "{$cat->id},{$cat->contextid}"; 183 qtype_multichoice_edit_form::mock_submit((array)$formdata); 184 185 $form = \qtype_multichoice_test_helper::get_question_editing_form($cat, $questiondata); 186 187 $this->assertTrue($form->is_validated()); 188 189 $fromform = $form->get_data(); 190 191 $returnedfromsave = $this->qtype->save_question($questiondata, $fromform); 192 193 // Now get just the raw DB record. 194 $question = $DB->get_record('question', ['id' => $returnedfromsave->id], '*', MUST_EXIST); 195 196 // Load it. 197 $this->qtype->get_question_options($question); 198 $this->assertDebuggingNotCalled(); 199 $this->assertInstanceOf(\stdClass::class, $question->options); 200 201 $options = $question->options; 202 $this->assertEquals($question->id, $options->questionid); 203 $this->assertEquals(0, $options->single); 204 205 $this->assertCount(4, $options->answers); 206 207 // Now we are going to delete the options record. 208 $DB->delete_records('qtype_multichoice_options', ['questionid' => $question->id]); 209 210 // Now see what happens. 211 $question = $DB->get_record('question', ['id' => $returnedfromsave->id], '*', MUST_EXIST); 212 $this->qtype->get_question_options($question); 213 214 $this->assertDebuggingCalled('Question ID '.$question->id.' was missing an options record. Using default.'); 215 $this->assertInstanceOf(\stdClass::class, $question->options); 216 $options = $question->options; 217 $this->assertEquals($question->id, $options->questionid); 218 $this->assertCount(4, $options->answers); 219 220 $this->assertEquals(get_string('correctfeedbackdefault', 'question'), $options->correctfeedback); 221 $this->assertEquals(FORMAT_HTML, $options->correctfeedbackformat); 222 223 // We no longer know how many answers, so it just has to guess with the default value. 224 $this->assertEquals(get_config('qtype_multichoice', 'answerhowmany'), $options->single); 225 226 // And finally we try again with no answer either. 227 $DB->delete_records('question_answers', ['question' => $question->id]); 228 229 $question = $DB->get_record('question', ['id' => $returnedfromsave->id], '*', MUST_EXIST); 230 $this->qtype->get_question_options($question); 231 232 $this->assertDebuggingCalled('Question ID '.$question->id.' was missing an options record. Using default.'); 233 $this->assertInstanceOf(\stdClass::class, $question->options); 234 $options = $question->options; 235 $this->assertEquals($question->id, $options->questionid); 236 $this->assertCount(0, $options->answers); 237 } 238 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body