[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/question/behaviour/interactive/tests/ -> walkthrough_test.php (source)

   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  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1