Differences Between: [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 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(array($returnedfromsave->id)); 131 $actualquestiondata = end($actualquestionsdata); 132 133 foreach ($questiondata as $property => $value) { 134 if (!in_array($property, array('id', 'version', 'timemodified', 'timecreated', 'options', 'hints', 'stamp'))) { 135 $this->assertEquals($value, $actualquestiondata->$property); 136 } 137 } 138 139 foreach ($questiondata->options as $optionname => $value) { 140 if ($optionname != 'answers') { 141 $this->assertEquals($value, $actualquestiondata->options->$optionname); 142 } 143 } 144 145 foreach ($questiondata->hints as $hint) { 146 $actualhint = array_shift($actualquestiondata->hints); 147 foreach ($hint as $property => $value) { 148 if (!in_array($property, array('id', 'questionid', 'options'))) { 149 $this->assertEquals($value, $actualhint->$property); 150 } 151 } 152 } 153 154 foreach ($questiondata->options->answers as $answer) { 155 $actualanswer = array_shift($actualquestiondata->options->answers); 156 foreach ($answer as $ansproperty => $ansvalue) { 157 // This question does not use 'answerformat', will ignore it. 158 if (!in_array($ansproperty, array('id', 'question', 'answerformat'))) { 159 $this->assertEquals($ansvalue, $actualanswer->$ansproperty); 160 } 161 } 162 } 163 } 164 165 /** 166 * Test to make sure that loading of question options works, including in an error case. 167 */ 168 public function test_get_question_options() { 169 global $DB; 170 171 $this->resetAfterTest(true); 172 $this->setAdminUser(); 173 174 // Create a complete, in DB question to use. 175 $questiondata = \test_question_maker::get_question_data('multichoice', 'two_of_four'); 176 $formdata = \test_question_maker::get_question_form_data('multichoice', 'two_of_four'); 177 178 $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); 179 $cat = $generator->create_question_category(array()); 180 181 $formdata->category = "{$cat->id},{$cat->contextid}"; 182 qtype_multichoice_edit_form::mock_submit((array)$formdata); 183 184 $form = \qtype_multichoice_test_helper::get_question_editing_form($cat, $questiondata); 185 186 $this->assertTrue($form->is_validated()); 187 188 $fromform = $form->get_data(); 189 190 $returnedfromsave = $this->qtype->save_question($questiondata, $fromform); 191 192 // Now get just the raw DB record. 193 $question = $DB->get_record('question', ['id' => $returnedfromsave->id], '*', MUST_EXIST); 194 195 // Load it. 196 $this->qtype->get_question_options($question); 197 $this->assertDebuggingNotCalled(); 198 $this->assertInstanceOf(\stdClass::class, $question->options); 199 200 $options = $question->options; 201 $this->assertEquals($question->id, $options->questionid); 202 $this->assertEquals(0, $options->single); 203 204 $this->assertCount(4, $options->answers); 205 206 // Now we are going to delete the options record. 207 $DB->delete_records('qtype_multichoice_options', ['questionid' => $question->id]); 208 209 // Now see what happens. 210 $question = $DB->get_record('question', ['id' => $returnedfromsave->id], '*', MUST_EXIST); 211 $this->qtype->get_question_options($question); 212 213 $this->assertDebuggingCalled('Question ID '.$question->id.' was missing an options record. Using default.'); 214 $this->assertInstanceOf(\stdClass::class, $question->options); 215 $options = $question->options; 216 $this->assertEquals($question->id, $options->questionid); 217 $this->assertCount(4, $options->answers); 218 219 $this->assertEquals(get_string('correctfeedbackdefault', 'question'), $options->correctfeedback); 220 $this->assertEquals(FORMAT_HTML, $options->correctfeedbackformat); 221 222 // We no longer know how many answers, so it just has to guess with the default value. 223 $this->assertEquals(get_config('qtype_multichoice', 'answerhowmany'), $options->single); 224 225 // And finally we try again with no answer either. 226 $DB->delete_records('question_answers', ['question' => $question->id]); 227 228 $question = $DB->get_record('question', ['id' => $returnedfromsave->id], '*', MUST_EXIST); 229 $this->qtype->get_question_options($question); 230 231 $this->assertDebuggingCalled('Question ID '.$question->id.' was missing an options record. Using default.'); 232 $this->assertInstanceOf(\stdClass::class, $question->options); 233 $options = $question->options; 234 $this->assertEquals($question->id, $options->questionid); 235 $this->assertCount(0, $options->answers); 236 } 237 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body