Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/question/behaviour/interactive/simpletest/testwalkthrough.php
Go to the documentation of this file.
00001 <?php
00002 // This file is part of Moodle - http://moodle.org/
00003 //
00004 // Moodle is free software: you can redistribute it and/or modify
00005 // it under the terms of the GNU General Public License as published by
00006 // the Free Software Foundation, either version 3 of the License, or
00007 // (at your option) any later version.
00008 //
00009 // Moodle is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00016 
00028 defined('MOODLE_INTERNAL') || die();
00029 
00030 require_once(dirname(__FILE__) . '/../../../engine/lib.php');
00031 require_once(dirname(__FILE__) . '/../../../engine/simpletest/helpers.php');
00032 
00033 
00040 class qbehaviour_interactive_walkthrough_test extends qbehaviour_walkthrough_test_base {
00041 
00042     public function test_interactive_feedback_multichoice_right() {
00043 
00044         // Create a multichoice single question.
00045         $mc = test_question_maker::make_a_multichoice_single_question();
00046         $mc->hints = array(
00047             new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, false, false),
00048             new question_hint_with_parts(0, 'This is the second hint.', FORMAT_HTML, true, true),
00049         );
00050         $this->start_attempt_at_question($mc, 'interactive');
00051 
00052         $rightindex = $this->get_mc_right_answer_index($mc);
00053         $wrongindex = ($rightindex + 1) % 3;
00054 
00055         // Check the initial state.
00056         $this->check_current_state(question_state::$todo);
00057         $this->check_current_mark(null);
00058         $this->check_current_output(
00059                 $this->get_contains_marked_out_of_summary(),
00060                 $this->get_contains_question_text_expectation($mc),
00061                 $this->get_contains_mc_radio_expectation(0, true, false),
00062                 $this->get_contains_mc_radio_expectation(1, true, false),
00063                 $this->get_contains_mc_radio_expectation(2, true, false),
00064                 $this->get_contains_submit_button_expectation(true),
00065                 $this->get_does_not_contain_feedback_expectation(),
00066                 $this->get_tries_remaining_expectation(3),
00067                 $this->get_no_hint_visible_expectation());
00068 
00069         // Save the wrong answer.
00070         $this->process_submission(array('answer' => $wrongindex));
00071 
00072         // Verify.
00073         $this->check_current_state(question_state::$todo);
00074         $this->check_current_mark(null);
00075         $this->check_current_output(
00076                 $this->get_contains_marked_out_of_summary(),
00077                 $this->get_contains_mc_radio_expectation($wrongindex, true, true),
00078                 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, true, false),
00079                 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, true, false),
00080                 $this->get_contains_submit_button_expectation(true),
00081                 $this->get_does_not_contain_correctness_expectation(),
00082                 $this->get_does_not_contain_feedback_expectation(),
00083                 $this->get_tries_remaining_expectation(3),
00084                 $this->get_no_hint_visible_expectation());
00085 
00086         // Submit the wrong answer.
00087         $this->process_submission(array('answer' => $wrongindex, '-submit' => 1));
00088 
00089         // Verify.
00090         $this->check_current_state(question_state::$todo);
00091         $this->check_current_mark(null);
00092         $this->check_current_output(
00093                 $this->get_contains_marked_out_of_summary(),
00094                 $this->get_contains_mc_radio_expectation($wrongindex, false, true),
00095                 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, false, false),
00096                 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, false, false),
00097                 $this->get_contains_submit_button_expectation(false),
00098                 $this->get_contains_try_again_button_expectation(true),
00099                 $this->get_does_not_contain_correctness_expectation(),
00100                 new PatternExpectation('/' .
00101                         preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'),
00102                 $this->get_contains_hint_expectation('This is the first hint'));
00103 
00104         // Check that, if we review in this state, the try again button is disabled.
00105         $displayoptions = new question_display_options();
00106         $displayoptions->readonly = true;
00107         $html = $this->quba->render_question($this->slot, $displayoptions);
00108         $this->assert($this->get_contains_try_again_button_expectation(false), $html);
00109 
00110         // Do try again.
00111         $this->process_submission(array('-tryagain' => 1));
00112 
00113         // Verify.
00114         $this->check_current_state(question_state::$todo);
00115         $this->check_current_mark(null);
00116         $this->check_current_output(
00117                 $this->get_contains_marked_out_of_summary(),
00118                 $this->get_contains_mc_radio_expectation($wrongindex, true, true),
00119                 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, true, false),
00120                 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, true, false),
00121                 $this->get_contains_submit_button_expectation(true),
00122                 $this->get_does_not_contain_correctness_expectation(),
00123                 $this->get_does_not_contain_feedback_expectation(),
00124                 $this->get_tries_remaining_expectation(2),
00125                 $this->get_no_hint_visible_expectation());
00126 
00127         // Submit the right answer.
00128         $this->process_submission(array('answer' => $rightindex, '-submit' => 1));
00129 
00130         // Verify.
00131         $this->check_current_state(question_state::$gradedright);
00132         $this->check_current_mark(0.6666667);
00133         $this->check_current_output(
00134                 $this->get_contains_mark_summary(0.6666667),
00135                 $this->get_contains_mc_radio_expectation($rightindex, false, true),
00136                 $this->get_contains_mc_radio_expectation(($rightindex + 1) % 3, false, false),
00137                 $this->get_contains_mc_radio_expectation(($rightindex + 1) % 3, false, false),
00138                 $this->get_contains_submit_button_expectation(false),
00139                 $this->get_contains_correct_expectation(),
00140                 $this->get_no_hint_visible_expectation());
00141 
00142         // Finish the attempt - should not need to add a new state.
00143         $numsteps = $this->get_step_count();
00144         $this->quba->finish_all_questions();
00145 
00146         // Verify.
00147         $this->assertEqual($numsteps, $this->get_step_count());
00148         $this->check_current_state(question_state::$gradedright);
00149         $this->check_current_mark(0.6666667);
00150         $this->check_current_output(
00151                 $this->get_contains_mark_summary(0.6666667),
00152                 $this->get_contains_mc_radio_expectation($rightindex, false, true),
00153                 $this->get_contains_mc_radio_expectation(($rightindex + 1) % 3, false, false),
00154                 $this->get_contains_mc_radio_expectation(($rightindex + 1) % 3, false, false),
00155                 $this->get_contains_correct_expectation(),
00156                 $this->get_no_hint_visible_expectation());
00157 
00158         // Process a manual comment.
00159         $this->manual_grade('Not good enough!', 0.5);
00160 
00161         // Verify.
00162         $this->check_current_state(question_state::$mangrpartial);
00163         $this->check_current_mark(0.5);
00164         $this->check_current_output(
00165                 $this->get_contains_mark_summary(0.5),
00166                 $this->get_contains_partcorrect_expectation(),
00167                 new PatternExpectation('/' . preg_quote('Not good enough!') . '/'));
00168 
00169         // Check regrading does not mess anything up.
00170         $this->quba->regrade_all_questions();
00171 
00172         // Verify.
00173         $this->check_current_state(question_state::$mangrpartial);
00174         $this->check_current_mark(0.5);
00175         $this->check_current_output(
00176                 $this->get_contains_mark_summary(0.5),
00177                 $this->get_contains_partcorrect_expectation());
00178 
00179         $autogradedstep = $this->get_step($this->get_step_count() - 2);
00180         $this->assertWithinMargin($autogradedstep->get_fraction(), 0.6666667, 0.0000001);
00181     }
00182 
00183     public function test_interactive_finish_when_try_again_showing() {
00184 
00185         // Create a multichoice single question.
00186         $mc = test_question_maker::make_a_multichoice_single_question();
00187         $mc->hints = array(
00188             new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, false, false),
00189         );
00190         $this->start_attempt_at_question($mc, 'interactive');
00191 
00192         $rightindex = $this->get_mc_right_answer_index($mc);
00193         $wrongindex = ($rightindex + 1) % 3;
00194 
00195         // Check the initial state.
00196         $this->check_current_state(question_state::$todo);
00197         $this->check_current_mark(null);
00198         $this->check_current_output(
00199                 $this->get_contains_marked_out_of_summary(),
00200                 $this->get_contains_question_text_expectation($mc),
00201                 $this->get_contains_mc_radio_expectation(0, true, false),
00202                 $this->get_contains_mc_radio_expectation(1, true, false),
00203                 $this->get_contains_mc_radio_expectation(2, true, false),
00204                 $this->get_contains_submit_button_expectation(true),
00205                 $this->get_does_not_contain_feedback_expectation(),
00206                 $this->get_tries_remaining_expectation(2),
00207                 $this->get_no_hint_visible_expectation(),
00208                 new PatternExpectation('/' .
00209                         preg_quote(get_string('selectone', 'qtype_multichoice'), '/') . '/'));
00210 
00211         // Submit the wrong answer.
00212         $this->process_submission(array('answer' => $wrongindex, '-submit' => 1));
00213 
00214         // Verify.
00215         $this->check_current_state(question_state::$todo);
00216         $this->check_current_mark(null);
00217         $this->check_current_output(
00218                 $this->get_contains_marked_out_of_summary(),
00219                 $this->get_contains_mc_radio_expectation($wrongindex, false, true),
00220                 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, false, false),
00221                 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, false, false),
00222                 $this->get_contains_submit_button_expectation(false),
00223                 $this->get_contains_try_again_button_expectation(true),
00224                 $this->get_does_not_contain_correctness_expectation(),
00225                 new PatternExpectation('/' .
00226                         preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'),
00227                 $this->get_contains_hint_expectation('This is the first hint'));
00228 
00229         // Finish the attempt.
00230         $this->quba->finish_all_questions();
00231 
00232         // Verify.
00233         $this->check_current_state(question_state::$gradedwrong);
00234         $this->check_current_mark(0);
00235         $this->check_current_output(
00236                 $this->get_contains_mark_summary(0),
00237                 $this->get_contains_mc_radio_expectation($wrongindex, false, true),
00238                 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, false, false),
00239                 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, false, false),
00240                 $this->get_contains_incorrect_expectation(),
00241                 $this->get_no_hint_visible_expectation());
00242     }
00243 
00244     public function test_interactive_shortanswer_try_to_submit_blank() {
00245 
00246         // Create a short answer question.
00247         $sa = test_question_maker::make_question('shortanswer');
00248         $sa->hints = array(
00249             new question_hint(0, 'This is the first hint.', FORMAT_HTML),
00250             new question_hint(0, 'This is the second hint.', FORMAT_HTML),
00251         );
00252         $this->start_attempt_at_question($sa, 'interactive');
00253 
00254         // Check the initial state.
00255         $this->check_current_state(question_state::$todo);
00256         $this->check_current_mark(null);
00257         $this->check_current_output(
00258                 $this->get_contains_marked_out_of_summary(),
00259                 $this->get_contains_submit_button_expectation(true),
00260                 $this->get_does_not_contain_feedback_expectation(),
00261                 $this->get_does_not_contain_validation_error_expectation(),
00262                 $this->get_does_not_contain_try_again_button_expectation(),
00263                 $this->get_no_hint_visible_expectation());
00264 
00265         // Submit blank.
00266         $this->process_submission(array('-submit' => 1, 'answer' => ''));
00267 
00268         // Verify.
00269         $this->check_current_state(question_state::$invalid);
00270         $this->check_current_mark(null);
00271         $this->check_current_output(
00272                 $this->get_contains_marked_out_of_summary(),
00273                 $this->get_contains_submit_button_expectation(true),
00274                 $this->get_does_not_contain_feedback_expectation(),
00275                 $this->get_contains_validation_error_expectation(),
00276                 $this->get_does_not_contain_try_again_button_expectation(),
00277                 $this->get_no_hint_visible_expectation());
00278 
00279         // Now get it wrong.
00280         $this->process_submission(array('-submit' => 1, 'answer' => 'newt'));
00281 
00282         // Verify.
00283         $this->check_current_state(question_state::$todo);
00284         $this->check_current_mark(null);
00285         $this->check_current_output(
00286                 $this->get_contains_marked_out_of_summary(),
00287                 $this->get_contains_submit_button_expectation(false),
00288                 $this->get_does_not_contain_validation_error_expectation(),
00289                 $this->get_contains_try_again_button_expectation(true),
00290                 new PatternExpectation('/' .
00291                         preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'),
00292                 $this->get_contains_hint_expectation('This is the first hint'));
00293         $this->assertEqual('newt',
00294                 $this->quba->get_response_summary($this->slot));
00295 
00296         // Try again.
00297         $this->process_submission(array('-tryagain' => 1));
00298 
00299         // Verify.
00300         $this->check_current_state(question_state::$todo);
00301         $this->check_current_mark(null);
00302         $this->check_current_output(
00303                 $this->get_contains_marked_out_of_summary(),
00304                 $this->get_contains_submit_button_expectation(true),
00305                 $this->get_does_not_contain_feedback_expectation(),
00306                 $this->get_does_not_contain_validation_error_expectation(),
00307                 $this->get_does_not_contain_try_again_button_expectation(),
00308                 $this->get_no_hint_visible_expectation());
00309 
00310         // Now submit blank again.
00311         $this->process_submission(array('-submit' => 1, 'answer' => ''));
00312 
00313         // Verify.
00314         $this->check_current_state(question_state::$invalid);
00315         $this->check_current_mark(null);
00316         $this->check_current_output(
00317                 $this->get_contains_marked_out_of_summary(),
00318                 $this->get_contains_submit_button_expectation(true),
00319                 $this->get_does_not_contain_feedback_expectation(),
00320                 $this->get_contains_validation_error_expectation(),
00321                 $this->get_does_not_contain_try_again_button_expectation(),
00322                 $this->get_no_hint_visible_expectation());
00323 
00324         // Now get it right.
00325         $this->process_submission(array('-submit' => 1, 'answer' => 'frog'));
00326 
00327         // Verify.
00328         $this->check_current_state(question_state::$gradedright);
00329         $this->check_current_mark(0.6666667);
00330         $this->check_current_output(
00331                 $this->get_contains_mark_summary(0.6666667),
00332                 $this->get_contains_submit_button_expectation(false),
00333                 $this->get_contains_correct_expectation(),
00334                 $this->get_does_not_contain_validation_error_expectation(),
00335                 $this->get_no_hint_visible_expectation());
00336         $this->assertEqual('frog',
00337                 $this->quba->get_response_summary($this->slot));
00338     }
00339 
00340     public function test_interactive_feedback_multichoice_multiple_reset() {
00341 
00342         // Create a multichoice multiple question.
00343         $mc = test_question_maker::make_a_multichoice_multi_question();
00344         $mc->hints = array(
00345             new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, true, true),
00346             new question_hint_with_parts(0, 'This is the second hint.', FORMAT_HTML, true, true),
00347         );
00348         $this->start_attempt_at_question($mc, 'interactive', 2);
00349 
00350         $right = array_keys($mc->get_correct_response());
00351         $wrong = array_diff(array('choice0', 'choice1', 'choice2', 'choice3'), $right);
00352         $wrong = array_values(array_diff(
00353                 array('choice0', 'choice1', 'choice2', 'choice3'), $right));
00354 
00355         // Check the initial state.
00356         $this->check_current_state(question_state::$todo);
00357         $this->check_current_mark(null);
00358         $this->check_current_output(
00359                 $this->get_contains_marked_out_of_summary(),
00360                 $this->get_contains_question_text_expectation($mc),
00361                 $this->get_contains_mc_checkbox_expectation('choice0', true, false),
00362                 $this->get_contains_mc_checkbox_expectation('choice1', true, false),
00363                 $this->get_contains_mc_checkbox_expectation('choice2', true, false),
00364                 $this->get_contains_mc_checkbox_expectation('choice3', true, false),
00365                 $this->get_contains_submit_button_expectation(true),
00366                 $this->get_does_not_contain_feedback_expectation(),
00367                 $this->get_does_not_contain_num_parts_correct(),
00368                 $this->get_tries_remaining_expectation(3),
00369                 $this->get_no_hint_visible_expectation(),
00370                 new PatternExpectation('/' .
00371                         preg_quote(get_string('selectmulti', 'qtype_multichoice'), '/') . '/'));
00372 
00373         // Submit an answer with one right, and one wrong.
00374         $this->process_submission(array($right[0] => 1, $wrong[0] => 1, '-submit' => 1));
00375 
00376         // Verify.
00377         $this->check_current_state(question_state::$todo);
00378         $this->check_current_mark(null);
00379         $this->check_current_output(
00380                 $this->get_contains_marked_out_of_summary(),
00381                 $this->get_contains_mc_checkbox_expectation($right[0], false, true),
00382                 $this->get_contains_mc_checkbox_expectation($right[1], false, false),
00383                 $this->get_contains_mc_checkbox_expectation($wrong[0], false, true),
00384                 $this->get_contains_mc_checkbox_expectation($wrong[1], false, false),
00385                 $this->get_contains_submit_button_expectation(false),
00386                 $this->get_contains_try_again_button_expectation(true),
00387                 $this->get_does_not_contain_correctness_expectation(),
00388                 new PatternExpectation('/' .
00389                         preg_quote(get_string('notcomplete', 'qbehaviour_interactive')) . '/'),
00390                 $this->get_contains_hint_expectation('This is the first hint'),
00391                 $this->get_contains_num_parts_correct(1),
00392                 $this->get_contains_standard_incorrect_combined_feedback_expectation(),
00393                 $this->get_contains_hidden_expectation(
00394                         $this->quba->get_field_prefix($this->slot) . $right[0], '1'),
00395                 $this->get_does_not_contain_hidden_expectation(
00396                         $this->quba->get_field_prefix($this->slot) . $right[1]),
00397                 $this->get_contains_hidden_expectation(
00398                         $this->quba->get_field_prefix($this->slot) . $wrong[0], '0'),
00399                 $this->get_does_not_contain_hidden_expectation(
00400                         $this->quba->get_field_prefix($this->slot) . $wrong[1]));
00401 
00402         // Do try again.
00403         $this->process_submission(array($right[0] => 1, '-tryagain' => 1));
00404 
00405         // Verify.
00406         $this->check_current_state(question_state::$todo);
00407         $this->check_current_mark(null);
00408         $this->check_current_output(
00409                 $this->get_contains_marked_out_of_summary(),
00410                 $this->get_contains_mc_checkbox_expectation($right[0], true, true),
00411                 $this->get_contains_mc_checkbox_expectation($right[1], true, false),
00412                 $this->get_contains_mc_checkbox_expectation($wrong[0], true, false),
00413                 $this->get_contains_mc_checkbox_expectation($wrong[1], true, false),
00414                 $this->get_contains_submit_button_expectation(true),
00415                 $this->get_does_not_contain_correctness_expectation(),
00416                 $this->get_does_not_contain_feedback_expectation(),
00417                 $this->get_tries_remaining_expectation(2),
00418                 $this->get_no_hint_visible_expectation());
00419     }
00420 
00421     public function test_interactive_regrade_changing_num_tries_leaving_open() {
00422         // Create a multichoice multiple question.
00423         $q = test_question_maker::make_question('shortanswer');
00424         $q->hints = array(
00425             new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, true, true),
00426             new question_hint_with_parts(0, 'This is the second hint.', FORMAT_HTML, true, true),
00427         );
00428         $this->start_attempt_at_question($q, 'interactive', 3);
00429 
00430         // Check the initial state.
00431         $this->check_current_state(question_state::$todo);
00432         $this->check_current_mark(null);
00433         $this->check_current_output(
00434                 $this->get_tries_remaining_expectation(3));
00435 
00436         // Submit the right answer.
00437         $this->process_submission(array('answer' => 'frog', '-submit' => 1));
00438 
00439         // Verify.
00440         $this->check_current_state(question_state::$gradedright);
00441         $this->check_current_mark(3);
00442 
00443         // Now change the quiestion so that answer is only partially right, and regrade.
00444         $q->answers[13]->fraction = 0.6666667;
00445         $q->answers[14]->fraction = 1;
00446 
00447         $this->quba->regrade_all_questions(false);
00448 
00449         // Verify.
00450         $this->check_current_state(question_state::$todo);
00451         $this->check_current_mark(null);
00452     }
00453 
00454     public function test_interactive_regrade_changing_num_tries_finished() {
00455         // Create a multichoice multiple question.
00456         $q = test_question_maker::make_question('shortanswer');
00457         $q->hints = array(
00458             new question_hint_with_parts(0, 'This is the first hint.', FORMAT_HTML, true, true),
00459             new question_hint_with_parts(0, 'This is the second hint.', FORMAT_HTML, true, true),
00460         );
00461         $this->start_attempt_at_question($q, 'interactive', 3);
00462 
00463         // Check the initial state.
00464         $this->check_current_state(question_state::$todo);
00465         $this->check_current_mark(null);
00466         $this->check_current_output(
00467                 $this->get_tries_remaining_expectation(3));
00468 
00469         // Submit the right answer.
00470         $this->process_submission(array('answer' => 'frog', '-submit' => 1));
00471 
00472         // Verify.
00473         $this->check_current_state(question_state::$gradedright);
00474         $this->check_current_mark(3);
00475 
00476         // Now change the quiestion so that answer is only partially right, and regrade.
00477         $q->answers[13]->fraction = 0.6666667;
00478         $q->answers[14]->fraction = 1;
00479 
00480         $this->quba->regrade_all_questions(true);
00481 
00482         // Verify.
00483         $this->check_current_state(question_state::$gradedpartial);
00484         // TODO I don't think 1 is the right fraction here. However, it is what
00485         // you get attempting a question like this without regrading being involved,
00486         // and I am currently interested in testing regrading here.
00487         $this->check_current_mark(1);
00488     }
00489 }
 All Data Structures Namespaces Files Functions Variables Enumerations