|
Moodle
2.2.1
http://www.collinsharper.com
|
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 }