See Release Notes
Long Term Support Release
Differences Between: [Versions 311 and 401] [Versions 400 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 /** 18 * This file contains tests for the question_engine class. 19 * 20 * @package moodlecore 21 * @subpackage questionengine 22 * @copyright 2009 The Open University 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 namespace core_question; 27 28 use advanced_testcase; 29 use moodle_exception; 30 use question_engine; 31 32 /** 33 * Unit tests for the question_engine class. 34 * 35 * @copyright 2009 The Open University 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 * @coversDefaultClass \question_engine 38 */ 39 class question_engine_test extends advanced_testcase { 40 41 /** 42 * Load required libraries. 43 */ 44 public static function setUpBeforeClass(): void { 45 global $CFG; 46 47 require_once("{$CFG->dirroot}/question/engine/lib.php"); 48 } 49 50 /** 51 * Tests for load_behaviour_class. 52 * 53 * @covers \question_engine::load_behaviour_class 54 */ 55 public function test_load_behaviour_class(): void { 56 // Exercise SUT. 57 question_engine::load_behaviour_class('deferredfeedback'); 58 59 // Verify. 60 $this->assertTrue(class_exists('qbehaviour_deferredfeedback')); 61 } 62 63 /** 64 * Tests for load_behaviour_class when a class is missing. 65 * 66 * @covers \question_engine::load_behaviour_class 67 */ 68 public function test_load_behaviour_class_missing(): void { 69 // Exercise SUT. 70 $this->expectException(moodle_exception::class); 71 question_engine::load_behaviour_class('nonexistantbehaviour'); 72 } 73 74 /** 75 * Test the get_behaviour_unused_display_options with various options. 76 * 77 * @covers \question_engine::get_behaviour_unused_display_options 78 * @dataProvider get_behaviour_unused_display_options_provider 79 * @param string $behaviour 80 * @param array $expected 81 */ 82 public function test_get_behaviour_unused_display_options(string $behaviour, array $expected): void { 83 $this->assertEquals($expected, question_engine::get_behaviour_unused_display_options($behaviour)); 84 } 85 86 /** 87 * Data provider for get_behaviour_unused_display_options. 88 * 89 * @return array 90 */ 91 public function get_behaviour_unused_display_options_provider(): array { 92 return [ 93 'interactive' => [ 94 'interactive', 95 [], 96 ], 97 'deferredfeedback' => [ 98 'deferredfeedback', 99 ['correctness', 'marks', 'specificfeedback', 'generalfeedback', 'rightanswer'], 100 ], 101 'deferredcbm' => [ 102 'deferredcbm', 103 ['correctness', 'marks', 'specificfeedback', 'generalfeedback', 'rightanswer'], 104 ], 105 'manualgraded' => [ 106 'manualgraded', 107 ['correctness', 'marks', 'specificfeedback', 'generalfeedback', 'rightanswer'], 108 ], 109 ]; 110 } 111 112 /** 113 * Tests for can_questions_finish_during_the_attempt. 114 * 115 * @covers \question_engine::can_questions_finish_during_the_attempt 116 * @dataProvider can_questions_finish_during_the_attempt_provider 117 * @param string $behaviour 118 * @param bool $expected 119 */ 120 public function test_can_questions_finish_during_the_attempt(string $behaviour, bool $expected): void { 121 $this->assertEquals($expected, question_engine::can_questions_finish_during_the_attempt($behaviour)); 122 } 123 124 /** 125 * Data provider for can_questions_finish_during_the_attempt_provider. 126 * 127 * @return array 128 */ 129 public function can_questions_finish_during_the_attempt_provider(): array { 130 return [ 131 ['deferredfeedback', false], 132 ['interactive', true], 133 ]; 134 } 135 136 /** 137 * Tests for sort_behaviours 138 * 139 * @covers \question_engine::sort_behaviours 140 * @dataProvider sort_behaviours_provider 141 * @param array $input The params passed to sort_behaviours 142 * @param array $expected 143 */ 144 public function test_sort_behaviours(array $input, array $expected): void { 145 $this->assertSame($expected, question_engine::sort_behaviours(...$input)); 146 } 147 148 /** 149 * Data provider for sort_behaviours. 150 * 151 * @return array 152 */ 153 public function sort_behaviours_provider(): array { 154 $in = [ 155 'b1' => 'Behave 1', 156 'b2' => 'Behave 2', 157 'b3' => 'Behave 3', 158 'b4' => 'Behave 4', 159 'b5' => 'Behave 5', 160 'b6' => 'Behave 6', 161 ]; 162 163 return [ 164 [ 165 [$in, '', '', ''], 166 $in, 167 ], 168 [ 169 [$in, '', 'b4', 'b4'], 170 $in, 171 ], 172 [ 173 [$in, '', 'b1,b2,b3,b4', 'b4'], 174 ['b4' => 'Behave 4', 'b5' => 'Behave 5', 'b6' => 'Behave 6'], 175 ], 176 [ 177 [$in, 'b6,b1,b4', 'b2,b3,b4,b5', 'b4'], 178 ['b6' => 'Behave 6', 'b1' => 'Behave 1', 'b4' => 'Behave 4'], 179 ], 180 [ 181 [$in, 'b6,b5,b4', 'b1,b2,b3', 'b4'], 182 ['b6' => 'Behave 6', 'b5' => 'Behave 5', 'b4' => 'Behave 4'], 183 ], 184 [ 185 [$in, 'b1,b6,b5', 'b1,b2,b3,b4', 'b4'], 186 ['b6' => 'Behave 6', 'b5' => 'Behave 5', 'b4' => 'Behave 4'], 187 ], 188 [ 189 [$in, 'b2,b4,b6', 'b1,b3,b5', 'b2'], 190 ['b2' => 'Behave 2', 'b4' => 'Behave 4', 'b6' => 'Behave 6'], 191 ], 192 // Ignore unknown input in the order argument. 193 [ 194 [$in, 'unknown', '', ''], 195 $in, 196 ], 197 // Ignore unknown input in the disabled argument. 198 [ 199 [$in, '', 'unknown', ''], 200 $in, 201 ], 202 ]; 203 } 204 205 /** 206 * Tests for is_manual_grade_in_range. 207 * 208 * @dataProvider is_manual_grade_in_range_provider 209 * @covers \question_engine::is_manual_grade_in_range 210 * @param array $post The values to add to $_POST 211 * @param array $params The params to pass to is_manual_grade_in_range 212 * @param bool $expected 213 */ 214 public function test_is_manual_grade_in_range(array $post, array $params, bool $expected): void { 215 $_POST[] = $post; 216 $this->assertEquals($expected, question_engine::is_manual_grade_in_range(...$params)); 217 } 218 219 /** 220 * Data provider for is_manual_grade_in_range tests. 221 * 222 * @return array 223 */ 224 public function is_manual_grade_in_range_provider(): array { 225 return [ 226 'In range' => [ 227 'post' => [ 228 'q1:2_-mark' => 0.5, 229 'q1:2_-maxmark' => 1.0, 230 'q1:2_:minfraction' => 0, 231 'q1:2_:maxfraction' => 1, 232 ], 233 'range' => [1, 2], 234 'expected' => true, 235 ], 236 'Bottom end' => [ 237 'post' => [ 238 'q1:2_-mark' => -1.0, 239 'q1:2_-maxmark' => 2.0, 240 'q1:2_:minfraction' => -0.5, 241 'q1:2_:maxfraction' => 1, 242 ], 243 'range' => [1, 2], 244 'expected' => true, 245 ], 246 'Too low' => [ 247 'post' => [ 248 'q1:2_-mark' => -1.1, 249 'q1:2_-maxmark' => 2.0, 250 'q1:2_:minfraction' => -0.5, 251 'q1:2_:maxfraction' => 1, 252 ], 253 'range' => [1, 2], 254 'expected' => true, 255 ], 256 'Top end' => [ 257 'post' => [ 258 'q1:2_-mark' => 3.0, 259 'q1:2_-maxmark' => 1.0, 260 'q1:2_:minfraction' => -6.0, 261 'q1:2_:maxfraction' => 3.0, 262 ], 263 'range' => [1, 2], 264 'expected' => true, 265 ], 266 'Too high' => [ 267 'post' => [ 268 'q1:2_-mark' => 3.1, 269 'q1:2_-maxmark' => 1.0, 270 'q1:2_:minfraction' => -6.0, 271 'q1:2_:maxfraction' => 3.0, 272 ], 273 'range' => [1, 2], 274 'expected' => true, 275 ], 276 ]; 277 } 278 279 /** 280 * Tests for is_manual_grade_in_range. 281 * 282 * @covers \question_engine::is_manual_grade_in_range 283 */ 284 public function test_is_manual_grade_in_range_ungraded(): void { 285 $this->assertTrue(question_engine::is_manual_grade_in_range(1, 2)); 286 } 287 288 /** 289 * Ensure that the number renderer performs as expected. 290 * 291 * @covers \core_question_renderer::number 292 * @dataProvider render_question_number_provider 293 * @param mixed $value 294 * @param string $expected 295 */ 296 public function test_render_question_number($value, string $expected): void { 297 global $PAGE; 298 299 $renderer = new \core_question_renderer($PAGE, 'core_question'); 300 $rc = new \ReflectionClass($renderer); 301 $rcm = $rc->getMethod('number'); 302 $rcm->setAccessible(true); 303 304 $this->assertEquals($expected, $rcm->invoke($renderer, $value)); 305 } 306 307 /** 308 * Data provider for test_render_question_number. 309 * 310 * @return array 311 */ 312 public function render_question_number_provider(): array { 313 return [ 314 'Test with number is i character' => [ 315 'i', 316 '<h3 class="no">Information</h3>', 317 ], 318 'Test with number is empty string' => [ 319 '', 320 '', 321 ], 322 'Test with null' => [ 323 null, 324 '', 325 ], 326 'Test with number is 0' => [ 327 0, 328 '<h3 class="no">Question <span class="qno">0</span></h3>', 329 ], 330 'Test with number is numeric' => [ 331 1, 332 '<h3 class="no">Question <span class="qno">1</span></h3>', 333 ], 334 'Test with number is string' => [ 335 '1 of 2', 336 '<h3 class="no">Question <span class="qno">1 of 2</span></h3>', 337 ], 338 ]; 339 } 340 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body