[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 that walks a question through the interactive 19 * behaviour. 20 * 21 * @package qbehaviour 22 * @subpackage interactive 23 * @copyright 2009 The Open University 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 25 */ 26 27 28 defined('MOODLE_INTERNAL') || die(); 29 30 global $CFG; 31 require_once (__DIR__ . '/../../../engine/lib.php'); 32 require_once (__DIR__ . '/../../../engine/tests/helpers.php'); 33 34 35 /** 36 * Unit tests for the interactive behaviour. 37 * 38 * @copyright 2009 The Open University 39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 40 */ 41 class qbehaviour_interactive_walkthrough_test extends qbehaviour_walkthrough_test_base { 42 43 public function test_interactive_feedback_multichoice_right() { 44 45 // Create a multichoice single question. 46 $mc = test_question_maker::make_a_multichoice_single_question(); 47 $mc->hints = array( 48 new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, false, false), 49 new question_hint_with_parts(0, 'This is the second hint.', FORMAT_HTML, true, true), 50 ); 51 $this->start_attempt_at_question($mc, 'interactive'); 52 53 $rightindex = $this->get_mc_right_answer_index($mc); 54 $wrongindex = ($rightindex + 1) % 3; 55 56 // Check the initial state. 57 $this->check_current_state(question_state::$todo); 58 $this->check_current_mark(null); 59 $this->check_current_output( 60 $this->get_contains_marked_out_of_summary(), 61 $this->get_contains_question_text_expectation($mc), 62 $this->get_contains_mc_radio_expectation(0, true, false), 63 $this->get_contains_mc_radio_expectation(1, true, false), 64 $this->get_contains_mc_radio_expectation(2, true, false), 65 $this->get_contains_submit_button_expectation(true), 66 $this->get_does_not_contain_feedback_expectation(), 67 $this->get_tries_remaining_expectation(3), 68 $this->get_no_hint_visible_expectation()); 69 70 // Save the wrong answer. 71 $this->process_submission(array('answer' => $wrongindex)); 72 73 // Verify. 74 $this->check_current_state(question_state::$todo); 75 $this->check_current_mark(null); 76 $this->check_current_output( 77 $this->get_contains_marked_out_of_summary(), 78 $this->get_contains_mc_radio_expectation($wrongindex, true, true), 79 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, true, false), 80 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, true, false), 81 $this->get_contains_submit_button_expectation(true), 82 $this->get_does_not_contain_correctness_expectation(), 83 $this->get_does_not_contain_feedback_expectation(), 84 $this->get_tries_remaining_expectation(3), 85 $this->get_no_hint_visible_expectation()); 86 87 // Submit the wrong answer. 88 $this->process_submission(array('answer' => $wrongindex, '-submit' => 1)); 89 90 // Verify. 91 $this->check_current_state(question_state::$todo); 92 $this->check_current_mark(null); 93 $this->check_current_output( 94 $this->get_contains_marked_out_of_summary(), 95 $this->get_contains_mc_radio_expectation($wrongindex, false, true), 96 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, false, false), 97 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, false, false), 98 $this->get_does_not_contain_submit_button_expectation(), 99 $this->get_contains_try_again_button_expectation(true), 100 $this->get_does_not_contain_correctness_expectation(), 101 new question_pattern_expectation('/Tries remaining: 2/'), 102 $this->get_contains_hint_expectation('This is the first hint')); 103 104 // Check that, if we review in this state, the try again button is disabled. 105 $displayoptions = new question_display_options(); 106 $displayoptions->readonly = true; 107 $html = $this->quba->render_question($this->slot, $displayoptions); 108 $this->assert($this->get_contains_try_again_button_expectation(false), $html); 109 110 // Do try again. 111 $this->process_submission(array('-tryagain' => 1)); 112 113 // Verify. 114 $this->check_current_state(question_state::$todo); 115 $this->check_current_mark(null); 116 $this->check_current_output( 117 $this->get_contains_marked_out_of_summary(), 118 $this->get_contains_mc_radio_expectation($wrongindex, true, true), 119 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, true, false), 120 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, true, false), 121 $this->get_contains_submit_button_expectation(true), 122 $this->get_does_not_contain_correctness_expectation(), 123 $this->get_does_not_contain_feedback_expectation(), 124 $this->get_tries_remaining_expectation(2), 125 $this->get_no_hint_visible_expectation()); 126 127 // Submit the right answer. 128 $this->process_submission(array('answer' => $rightindex, '-submit' => 1)); 129 130 // Verify. 131 $this->check_current_state(question_state::$gradedright); 132 $this->check_current_mark(0.6666667); 133 $this->check_current_output( 134 $this->get_contains_mark_summary(0.6666667), 135 $this->get_contains_mc_radio_expectation($rightindex, false, true), 136 $this->get_contains_mc_radio_expectation(($rightindex + 1) % 3, false, false), 137 $this->get_contains_mc_radio_expectation(($rightindex + 1) % 3, false, false), 138 $this->get_does_not_contain_submit_button_expectation(), 139 $this->get_contains_correct_expectation(), 140 $this->get_no_hint_visible_expectation()); 141 142 // Finish the attempt - should not need to add a new state. 143 $numsteps = $this->get_step_count(); 144 $this->quba->finish_all_questions(); 145 146 // Verify. 147 $this->assertEquals($numsteps, $this->get_step_count()); 148 $this->check_current_state(question_state::$gradedright); 149 $this->check_current_mark(0.6666667); 150 $this->check_current_output( 151 $this->get_contains_mark_summary(0.6666667), 152 $this->get_contains_mc_radio_expectation($rightindex, false, true), 153 $this->get_contains_mc_radio_expectation(($rightindex + 1) % 3, false, false), 154 $this->get_contains_mc_radio_expectation(($rightindex + 1) % 3, false, false), 155 $this->get_contains_correct_expectation(), 156 $this->get_no_hint_visible_expectation()); 157 158 // Process a manual comment. 159 $this->manual_grade('Not good enough!', 0.5, FORMAT_HTML); 160 161 // Verify. 162 $this->check_current_state(question_state::$mangrpartial); 163 $this->check_current_mark(0.5); 164 $this->check_current_output( 165 $this->get_contains_mark_summary(0.5), 166 $this->get_contains_partcorrect_expectation(), 167 new question_pattern_expectation('/' . preg_quote('Not good enough!', '/') . '/')); 168 169 // Check regrading does not mess anything up. 170 $this->quba->regrade_all_questions(); 171 172 // Verify. 173 $this->check_current_state(question_state::$mangrpartial); 174 $this->check_current_mark(0.5); 175 $this->check_current_output( 176 $this->get_contains_mark_summary(0.5), 177 $this->get_contains_partcorrect_expectation()); 178 179 $autogradedstep = $this->get_step($this->get_step_count() - 2); 180 $this->assertEquals($autogradedstep->get_fraction(), 0.6666667, '', 0.0000001); 181 } 182 183 public function test_interactive_finish_when_try_again_showing() { 184 185 // Create a multichoice single question. 186 $mc = test_question_maker::make_a_multichoice_single_question(); 187 $mc->hints = array( 188 new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, false, false), 189 ); 190 $this->start_attempt_at_question($mc, 'interactive'); 191 192 $rightindex = $this->get_mc_right_answer_index($mc); 193 $wrongindex = ($rightindex + 1) % 3; 194 195 // Check the initial state. 196 $this->check_current_state(question_state::$todo); 197 $this->check_current_mark(null); 198 $this->check_current_output( 199 $this->get_contains_marked_out_of_summary(), 200 $this->get_contains_question_text_expectation($mc), 201 $this->get_contains_mc_radio_expectation(0, true, false), 202 $this->get_contains_mc_radio_expectation(1, true, false), 203 $this->get_contains_mc_radio_expectation(2, true, false), 204 $this->get_contains_submit_button_expectation(true), 205 $this->get_does_not_contain_feedback_expectation(), 206 $this->get_tries_remaining_expectation(2), 207 $this->get_no_hint_visible_expectation(), 208 new question_pattern_expectation('/' . 209 preg_quote(get_string('selectone', 'qtype_multichoice'), '/') . '/')); 210 211 // Submit the wrong answer. 212 $this->process_submission(array('answer' => $wrongindex, '-submit' => 1)); 213 214 // Verify. 215 $this->check_current_state(question_state::$todo); 216 $this->check_current_mark(null); 217 $this->check_current_output( 218 $this->get_contains_marked_out_of_summary(), 219 $this->get_contains_mc_radio_expectation($wrongindex, false, true), 220 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, false, false), 221 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, false, false), 222 $this->get_does_not_contain_submit_button_expectation(), 223 $this->get_contains_try_again_button_expectation(true), 224 $this->get_does_not_contain_correctness_expectation(), 225 new question_pattern_expectation('/Tries remaining: 1/'), 226 $this->get_contains_hint_expectation('This is the first hint')); 227 228 // Finish the attempt. 229 $this->quba->finish_all_questions(); 230 231 // Verify. 232 $this->check_current_state(question_state::$gradedwrong); 233 $this->check_current_mark(0); 234 $this->check_current_output( 235 $this->get_contains_mark_summary(0), 236 $this->get_contains_mc_radio_expectation($wrongindex, false, true), 237 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, false, false), 238 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, false, false), 239 $this->get_contains_incorrect_expectation(), 240 $this->get_no_hint_visible_expectation()); 241 } 242 243 public function test_interactive_shortanswer_try_to_submit_blank() { 244 245 // Create a short answer question. 246 $sa = test_question_maker::make_question('shortanswer'); 247 $sa->hints = array( 248 new question_hint(0, 'This is the first hint.', FORMAT_HTML), 249 new question_hint(0, 'This is the second hint.', FORMAT_HTML), 250 ); 251 $this->start_attempt_at_question($sa, 'interactive'); 252 253 // Check the initial state. 254 $this->check_current_state(question_state::$todo); 255 $this->check_current_mark(null); 256 $this->check_current_output( 257 $this->get_contains_marked_out_of_summary(), 258 $this->get_contains_submit_button_expectation(true), 259 $this->get_does_not_contain_feedback_expectation(), 260 $this->get_does_not_contain_validation_error_expectation(), 261 $this->get_does_not_contain_try_again_button_expectation(), 262 $this->get_no_hint_visible_expectation()); 263 264 // Submit blank. 265 $this->process_submission(array('-submit' => 1, 'answer' => '')); 266 267 // Verify. 268 $this->check_current_state(question_state::$invalid); 269 $this->check_current_mark(null); 270 $this->check_current_output( 271 $this->get_contains_marked_out_of_summary(), 272 $this->get_contains_submit_button_expectation(true), 273 $this->get_does_not_contain_feedback_expectation(), 274 $this->get_contains_validation_error_expectation(), 275 $this->get_does_not_contain_try_again_button_expectation(), 276 $this->get_no_hint_visible_expectation()); 277 278 // Now get it wrong. 279 $this->process_submission(array('-submit' => 1, 'answer' => 'newt')); 280 281 // Verify. 282 $this->check_current_state(question_state::$todo); 283 $this->check_current_mark(null); 284 $this->check_current_output( 285 $this->get_contains_marked_out_of_summary(), 286 $this->get_does_not_contain_submit_button_expectation(), 287 $this->get_does_not_contain_validation_error_expectation(), 288 $this->get_contains_try_again_button_expectation(true), 289 new question_pattern_expectation('/Tries remaining: 2/'), 290 $this->get_contains_hint_expectation('This is the first hint')); 291 $this->assertEquals('newt', 292 $this->quba->get_response_summary($this->slot)); 293 294 // Try again. 295 $this->process_submission(array('-tryagain' => 1)); 296 297 // Verify. 298 $this->check_current_state(question_state::$todo); 299 $this->check_current_mark(null); 300 $this->check_current_output( 301 $this->get_contains_marked_out_of_summary(), 302 $this->get_contains_submit_button_expectation(true), 303 $this->get_does_not_contain_feedback_expectation(), 304 $this->get_does_not_contain_validation_error_expectation(), 305 $this->get_does_not_contain_try_again_button_expectation(), 306 $this->get_no_hint_visible_expectation()); 307 308 // Now submit blank again. 309 $this->process_submission(array('-submit' => 1, 'answer' => '')); 310 311 // Verify. 312 $this->check_current_state(question_state::$invalid); 313 $this->check_current_mark(null); 314 $this->check_current_output( 315 $this->get_contains_marked_out_of_summary(), 316 $this->get_contains_submit_button_expectation(true), 317 $this->get_does_not_contain_feedback_expectation(), 318 $this->get_contains_validation_error_expectation(), 319 $this->get_does_not_contain_try_again_button_expectation(), 320 $this->get_no_hint_visible_expectation()); 321 322 // Now get it right. 323 $this->process_submission(array('-submit' => 1, 'answer' => 'frog')); 324 325 // Verify. 326 $this->check_current_state(question_state::$gradedright); 327 $this->check_current_mark(0.6666667); 328 $this->check_current_output( 329 $this->get_contains_mark_summary(0.6666667), 330 $this->get_does_not_contain_submit_button_expectation(), 331 $this->get_contains_correct_expectation(), 332 $this->get_does_not_contain_validation_error_expectation(), 333 $this->get_no_hint_visible_expectation()); 334 $this->assertEquals('frog', 335 $this->quba->get_response_summary($this->slot)); 336 } 337 338 public function test_interactive_feedback_multichoice_multiple_reset() { 339 340 // Create a multichoice multiple question. 341 $mc = test_question_maker::make_a_multichoice_multi_question(); 342 $mc->hints = array( 343 new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, true, true), 344 new question_hint_with_parts(0, 'This is the second hint.', FORMAT_HTML, true, true), 345 ); 346 $this->start_attempt_at_question($mc, 'interactive', 2); 347 348 $right = array_keys($mc->get_correct_response()); 349 $wrong = array_diff(array('choice0', 'choice1', 'choice2', 'choice3'), $right); 350 $wrong = array_values(array_diff( 351 array('choice0', 'choice1', 'choice2', 'choice3'), $right)); 352 353 // Check the initial state. 354 $this->check_current_state(question_state::$todo); 355 $this->check_current_mark(null); 356 $this->check_current_output( 357 $this->get_contains_marked_out_of_summary(), 358 $this->get_contains_question_text_expectation($mc), 359 $this->get_contains_mc_checkbox_expectation('choice0', true, false), 360 $this->get_contains_mc_checkbox_expectation('choice1', true, false), 361 $this->get_contains_mc_checkbox_expectation('choice2', true, false), 362 $this->get_contains_mc_checkbox_expectation('choice3', true, false), 363 $this->get_contains_submit_button_expectation(true), 364 $this->get_does_not_contain_feedback_expectation(), 365 $this->get_does_not_contain_num_parts_correct(), 366 $this->get_tries_remaining_expectation(3), 367 $this->get_no_hint_visible_expectation(), 368 new question_pattern_expectation('/' . 369 preg_quote(get_string('selectmulti', 'qtype_multichoice'), '/') . '/')); 370 371 // Submit an answer with one right, and one wrong. 372 $this->process_submission(array($right[0] => 1, $wrong[0] => 1, '-submit' => 1)); 373 374 // Verify. 375 $this->check_current_state(question_state::$todo); 376 $this->check_current_mark(null); 377 $this->check_current_output( 378 $this->get_contains_marked_out_of_summary(), 379 $this->get_contains_mc_checkbox_expectation($right[0], false, true), 380 $this->get_contains_mc_checkbox_expectation($right[1], false, false), 381 $this->get_contains_mc_checkbox_expectation($wrong[0], false, true), 382 $this->get_contains_mc_checkbox_expectation($wrong[1], false, false), 383 $this->get_does_not_contain_submit_button_expectation(), 384 $this->get_contains_try_again_button_expectation(true), 385 $this->get_does_not_contain_correctness_expectation(), 386 new question_pattern_expectation('/Tries remaining: 2/'), 387 $this->get_contains_hint_expectation('This is the first hint'), 388 $this->get_contains_num_parts_correct(1), 389 $this->get_contains_standard_incorrect_combined_feedback_expectation(), 390 $this->get_contains_hidden_expectation( 391 $this->quba->get_field_prefix($this->slot) . $right[0], '1'), 392 $this->get_does_not_contain_hidden_expectation( 393 $this->quba->get_field_prefix($this->slot) . $right[1]), 394 $this->get_contains_hidden_expectation( 395 $this->quba->get_field_prefix($this->slot) . $wrong[0], '0'), 396 $this->get_does_not_contain_hidden_expectation( 397 $this->quba->get_field_prefix($this->slot) . $wrong[1])); 398 399 // Do try again. 400 $this->process_submission(array($right[0] => 1, '-tryagain' => 1)); 401 402 // Verify. 403 $this->check_current_state(question_state::$todo); 404 $this->check_current_mark(null); 405 $this->check_current_output( 406 $this->get_contains_marked_out_of_summary(), 407 $this->get_contains_mc_checkbox_expectation($right[0], true, true), 408 $this->get_contains_mc_checkbox_expectation($right[1], true, false), 409 $this->get_contains_mc_checkbox_expectation($wrong[0], true, false), 410 $this->get_contains_mc_checkbox_expectation($wrong[1], true, false), 411 $this->get_contains_submit_button_expectation(true), 412 $this->get_does_not_contain_correctness_expectation(), 413 $this->get_does_not_contain_feedback_expectation(), 414 $this->get_tries_remaining_expectation(2), 415 $this->get_no_hint_visible_expectation()); 416 } 417 418 public function test_interactive_regrade_changing_num_tries_leaving_open() { 419 // Create a multichoice multiple question. 420 $q = test_question_maker::make_question('shortanswer'); 421 $q->hints = array( 422 new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, true, true), 423 new question_hint_with_parts(0, 'This is the second hint.', FORMAT_HTML, true, true), 424 ); 425 $this->start_attempt_at_question($q, 'interactive', 3); 426 427 // Check the initial state. 428 $this->check_current_state(question_state::$todo); 429 $this->check_current_mark(null); 430 $this->check_current_output( 431 $this->get_tries_remaining_expectation(3)); 432 433 // Submit the right answer. 434 $this->process_submission(array('answer' => 'frog', '-submit' => 1)); 435 436 // Verify. 437 $this->check_current_state(question_state::$gradedright); 438 $this->check_current_mark(3); 439 440 // Now change the quiestion so that answer is only partially right, and regrade. 441 $q->answers[13]->fraction = 0.6666667; 442 $q->answers[14]->fraction = 1; 443 444 $this->quba->regrade_all_questions(false); 445 446 // Verify. 447 $this->check_current_state(question_state::$todo); 448 $this->check_current_mark(null); 449 } 450 451 public function test_interactive_regrade_changing_num_tries_finished() { 452 // Create a multichoice multiple question. 453 $q = test_question_maker::make_question('shortanswer'); 454 $q->hints = array( 455 new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, true, true), 456 new question_hint_with_parts(0, 'This is the second hint.', FORMAT_HTML, true, true), 457 ); 458 $this->start_attempt_at_question($q, 'interactive', 3); 459 460 // Check the initial state. 461 $this->check_current_state(question_state::$todo); 462 $this->check_current_mark(null); 463 $this->check_current_output( 464 $this->get_tries_remaining_expectation(3)); 465 466 // Submit the right answer. 467 $this->process_submission(array('answer' => 'frog', '-submit' => 1)); 468 469 // Verify. 470 $this->check_current_state(question_state::$gradedright); 471 $this->check_current_mark(3); 472 473 // Now change the quiestion so that answer is only partially right, and regrade. 474 $q->answers[13]->fraction = 0.6666667; 475 $q->answers[14]->fraction = 1; 476 477 $this->quba->regrade_all_questions(true); 478 479 // Verify. 480 $this->check_current_state(question_state::$gradedpartial); 481 // TODO I don't think 1 is the right fraction here. However, it is what 482 // you get attempting a question like this without regrading being involved, 483 // and I am currently interested in testing regrading here. 484 $this->check_current_mark(1); 485 } 486 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |