Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]
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 * Unit tests for the essay question definition class. 19 * 20 * @package qtype 21 * @subpackage essay 22 * @copyright 2009 The Open University 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 global $CFG; 30 require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); 31 32 33 /** 34 * Unit tests for the matching question definition class. 35 * 36 * @copyright 2009 The Open University 37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 38 */ 39 class qtype_essay_question_test extends advanced_testcase { 40 public function test_get_question_summary() { 41 $essay = test_question_maker::make_an_essay_question(); 42 $essay->questiontext = 'Hello <img src="http://example.com/globe.png" alt="world" />'; 43 $this->assertEquals('Hello [world]', $essay->get_question_summary()); 44 } 45 46 /** 47 * Test summarise_response() when teachers view quiz attempts and then 48 * review them to see what has been saved in the response history table. 49 * 50 * @dataProvider summarise_response_provider 51 * @param int $responserequired 52 * @param int $attachmentsrequired 53 * @param string $answertext 54 * @param int $attachmentuploaded 55 * @param string $expected 56 */ 57 public function test_summarise_response(int $responserequired, int $attachmentsrequired, 58 string $answertext, int $attachmentuploaded, string $expected): void { 59 $this->resetAfterTest(); 60 61 // If number of allowed attachments is set to 'Unlimited', generate 10 attachments for testing purpose. 62 $numberofattachments = ($attachmentsrequired === -1) ? 10 : $attachmentsrequired; 63 64 // Create sample attachments. 65 $attachments = $this->create_user_and_sample_attachments($numberofattachments); 66 67 // Create the essay question under test. 68 $essay = test_question_maker::make_an_essay_question(); 69 $essay->start_attempt(new question_attempt_step(), 1); 70 71 $essay->responseformat = 'editor'; 72 $essay->responserequired = $responserequired; 73 $essay->attachmentsrequired = $attachmentsrequired; 74 75 $this->assertEquals($expected, $essay->summarise_response( 76 ['answer' => $answertext, 'answerformat' => FORMAT_HTML, 'attachments' => $attachments[$attachmentuploaded]])); 77 } 78 79 /** 80 * Data provider for summarise_response() test cases. 81 * 82 * @return array List of data sets (test cases) 83 */ 84 public function summarise_response_provider(): array { 85 return [ 86 'text input required, not attachments required' => 87 [1, 0, 'This is the text input for this essay.', 0, 'This is the text input for this essay.'], 88 'Text input required, one attachments required, one uploaded' => 89 [1, 1, 'This is the text input for this essay.', 1, 'This is the text input for this essay.Attachments: 0 (1 bytes)'], 90 'Text input is optional, four attachments required, one uploaded' => [0, 4, '', 1, 'Attachments: 0 (1 bytes)'], 91 'Text input is optional, four attachments required, two uploaded' => [0, 4, '', 2, 'Attachments: 0 (1 bytes), 1 (1 bytes)'], 92 'Text input is optional, four attachments required, three uploaded' => [0, 4, '', 3, 'Attachments: 0 (1 bytes), 1 (1 bytes), 2 (1 bytes)'], 93 'Text input is optional, four attachments required, four uploaded' => [0, 4, 'I have attached 4 files.', 4, 94 'I have attached 4 files.Attachments: 0 (1 bytes), 1 (1 bytes), 2 (1 bytes), 3 (1 bytes)'], 95 'Text input is optional, unlimited attachments required, one uploaded' => [0, -1, '', 1, 'Attachments: 0 (1 bytes)'], 96 'Text input is optional, unlimited attachments required, five uploaded' => [0, -1, 'I have attached 5 files.', 5, 97 'I have attached 5 files.Attachments: 0 (1 bytes), 1 (1 bytes), 2 (1 bytes), 3 (1 bytes), 4 (1 bytes)'], 98 'Text input is optional, unlimited attachments required, ten uploaded' => 99 [0, -1, '', 10, 'Attachments: 0 (1 bytes), 1 (1 bytes), 2 (1 bytes), 3 (1 bytes), 4 (1 bytes), ' . 100 '5 (1 bytes), 6 (1 bytes), 7 (1 bytes), 8 (1 bytes), 9 (1 bytes)'] 101 ]; 102 } 103 104 public function test_is_same_response() { 105 $essay = test_question_maker::make_an_essay_question(); 106 107 $essay->responsetemplate = ''; 108 109 $essay->start_attempt(new question_attempt_step(), 1); 110 111 $this->assertTrue($essay->is_same_response( 112 array(), 113 array('answer' => ''))); 114 115 $this->assertTrue($essay->is_same_response( 116 array('answer' => ''), 117 array('answer' => ''))); 118 119 $this->assertTrue($essay->is_same_response( 120 array('answer' => ''), 121 array())); 122 123 $this->assertFalse($essay->is_same_response( 124 array('answer' => 'Hello'), 125 array())); 126 127 $this->assertFalse($essay->is_same_response( 128 array('answer' => 'Hello'), 129 array('answer' => ''))); 130 131 $this->assertFalse($essay->is_same_response( 132 array('answer' => 0), 133 array('answer' => ''))); 134 135 $this->assertFalse($essay->is_same_response( 136 array('answer' => ''), 137 array('answer' => 0))); 138 139 $this->assertFalse($essay->is_same_response( 140 array('answer' => '0'), 141 array('answer' => ''))); 142 143 $this->assertFalse($essay->is_same_response( 144 array('answer' => ''), 145 array('answer' => '0'))); 146 } 147 148 public function test_is_same_response_with_template() { 149 $essay = test_question_maker::make_an_essay_question(); 150 151 $essay->responsetemplate = 'Once upon a time'; 152 153 $essay->start_attempt(new question_attempt_step(), 1); 154 155 $this->assertTrue($essay->is_same_response( 156 array(), 157 array('answer' => 'Once upon a time'))); 158 159 $this->assertTrue($essay->is_same_response( 160 array('answer' => ''), 161 array('answer' => 'Once upon a time'))); 162 163 $this->assertTrue($essay->is_same_response( 164 array('answer' => 'Once upon a time'), 165 array('answer' => ''))); 166 167 $this->assertTrue($essay->is_same_response( 168 array('answer' => ''), 169 array())); 170 171 $this->assertTrue($essay->is_same_response( 172 array('answer' => 'Once upon a time'), 173 array())); 174 175 $this->assertFalse($essay->is_same_response( 176 array('answer' => 0), 177 array('answer' => ''))); 178 179 $this->assertFalse($essay->is_same_response( 180 array('answer' => ''), 181 array('answer' => 0))); 182 183 $this->assertFalse($essay->is_same_response( 184 array('answer' => '0'), 185 array('answer' => ''))); 186 187 $this->assertFalse($essay->is_same_response( 188 array('answer' => ''), 189 array('answer' => '0'))); 190 } 191 192 public function test_is_complete_response() { 193 $this->resetAfterTest(true); 194 195 // Create sample attachments. 196 $attachments = $this->create_user_and_sample_attachments(); 197 198 // Create the essay question under test. 199 $essay = test_question_maker::make_an_essay_question(); 200 $essay->start_attempt(new question_attempt_step(), 1); 201 202 // Test the "traditional" case, where we must receive a response from the user. 203 $essay->responserequired = 1; 204 $essay->attachmentsrequired = 0; 205 $essay->responseformat = 'editor'; 206 207 // The empty string should be considered an incomplete response, as should a lack of a response. 208 $this->assertFalse($essay->is_complete_response(array('answer' => ''))); 209 $this->assertFalse($essay->is_complete_response(array())); 210 211 // Any nonempty string should be considered a complete response. 212 $this->assertTrue($essay->is_complete_response(array('answer' => 'A student response.'))); 213 $this->assertTrue($essay->is_complete_response(array('answer' => '0 times.'))); 214 $this->assertTrue($essay->is_complete_response(array('answer' => '0'))); 215 216 // Test the case where two files are required. 217 $essay->attachmentsrequired = 2; 218 219 // Attaching less than two files should result in an incomplete response. 220 $this->assertFalse($essay->is_complete_response(array('answer' => 'A'))); 221 $this->assertFalse($essay->is_complete_response( 222 array('answer' => 'A', 'attachments' => $attachments[0]))); 223 $this->assertFalse($essay->is_complete_response( 224 array('answer' => 'A', 'attachments' => $attachments[1]))); 225 226 // Anything without response text should result in an incomplete response. 227 $this->assertFalse($essay->is_complete_response( 228 array('answer' => '', 'attachments' => $attachments[2]))); 229 230 // Attaching two or more files should result in a complete response. 231 $this->assertTrue($essay->is_complete_response( 232 array('answer' => 'A', 'attachments' => $attachments[2]))); 233 $this->assertTrue($essay->is_complete_response( 234 array('answer' => 'A', 'attachments' => $attachments[3]))); 235 236 // Test the case in which two files are required, but the inline 237 // response is optional. 238 $essay->responserequired = 0; 239 240 $this->assertFalse($essay->is_complete_response( 241 array('answer' => '', 'attachments' => $attachments[1]))); 242 243 $this->assertTrue($essay->is_complete_response( 244 array('answer' => '', 'attachments' => $attachments[2]))); 245 246 // Test the case in which both the response and online text are optional. 247 $essay->attachmentsrequired = 0; 248 249 // Providing no answer and no attachment should result in an incomplete 250 // response. 251 $this->assertFalse($essay->is_complete_response( 252 array('answer' => ''))); 253 $this->assertFalse($essay->is_complete_response( 254 array('answer' => '', 'attachments' => $attachments[0]))); 255 256 // Providing an answer _or_ an attachment should result in a complete 257 // response. 258 $this->assertTrue($essay->is_complete_response( 259 array('answer' => '', 'attachments' => $attachments[1]))); 260 $this->assertTrue($essay->is_complete_response( 261 array('answer' => 'Answer text.', 'attachments' => $attachments[0]))); 262 263 // Test the case in which we're in "no inline response" mode, 264 // in which the response is not required (as it's not provided). 265 $essay->reponserequired = 0; 266 $essay->responseformat = 'noinline'; 267 $essay->attachmensrequired = 1; 268 269 $this->assertFalse($essay->is_complete_response( 270 array())); 271 $this->assertFalse($essay->is_complete_response( 272 array('attachments' => $attachments[0]))); 273 274 // Providing an attachment should result in a complete response. 275 $this->assertTrue($essay->is_complete_response( 276 array('attachments' => $attachments[1]))); 277 278 // Ensure that responserequired is ignored when we're in inline response mode. 279 $essay->reponserequired = 1; 280 $this->assertTrue($essay->is_complete_response( 281 array('attachments' => $attachments[1]))); 282 283 } 284 285 /** 286 * test_get_question_definition_for_external_rendering 287 */ 288 public function test_get_question_definition_for_external_rendering() { 289 $this->resetAfterTest(); 290 291 $essay = test_question_maker::make_an_essay_question(); 292 $essay->start_attempt(new question_attempt_step(), 1); 293 $qa = test_question_maker::get_a_qa($essay); 294 $displayoptions = new question_display_options(); 295 296 $options = $essay->get_question_definition_for_external_rendering($qa, $displayoptions); 297 $this->assertNotEmpty($options); 298 $this->assertEquals('editor', $options['responseformat']); 299 $this->assertEquals(1, $options['responserequired']); 300 $this->assertEquals(15, $options['responsefieldlines']); 301 $this->assertEquals(0, $options['attachments']); 302 $this->assertEquals(0, $options['attachmentsrequired']); 303 $this->assertNull($options['maxbytes']); 304 $this->assertNull($options['filetypeslist']); 305 $this->assertEquals('', $options['responsetemplate']); 306 $this->assertEquals(FORMAT_MOODLE, $options['responsetemplateformat']); 307 } 308 309 /** 310 * Create sample attachemnts and retun generated attachments. 311 * @param int $numberofattachments 312 * @return array 313 */ 314 private function create_user_and_sample_attachments($numberofattachments = 4) { 315 // Create a new logged-in user, so we can test responses with attachments. 316 $user = $this->getDataGenerator()->create_user(); 317 $this->setUser($user); 318 319 // Create sample attachments to use in testing. 320 $helper = test_question_maker::get_test_helper('essay'); 321 $attachments = []; 322 for ($i = 0; $i < ($numberofattachments + 1); ++$i) { 323 $attachments[$i] = $helper->make_attachments_saver($i); 324 } 325 return $attachments; 326 } 327 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body