Merge branch 'MDL-61971-master' of git://github.com/mickhawkins/moodle
[moodle.git] / question / behaviour / adaptive / tests / walkthrough_test.php
CommitLineData
603bd001
PS
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/**
19 * This file contains tests that walks a question through the adaptive
20 * behaviour.
21 *
22 * @package qbehaviour
23 * @subpackage adaptive
24 * @copyright 2009 The Open University
25 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 */
27
28
29defined('MOODLE_INTERNAL') || die();
30
31global $CFG;
1fcf0ca8
RS
32require_once(__DIR__ . '/../../../engine/lib.php');
33require_once(__DIR__ . '/../../../engine/tests/helpers.php');
603bd001
PS
34
35
36/**
37 * Unit tests for the adaptive behaviour.
38 *
39 * @copyright 2009 The Open University
40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41 */
42class qbehaviour_adaptive_walkthrough_test extends qbehaviour_walkthrough_test_base {
43 protected function get_contains_penalty_info_expectation($penalty) {
44 $penaltyinfo = get_string('gradingdetailspenalty', 'qbehaviour_adaptive',
45 format_float($penalty, $this->displayoptions->markdp));
03cefcc9 46 return new question_pattern_expectation('/'.preg_quote($penaltyinfo, '/').'/');
603bd001
PS
47 }
48
49 protected function get_does_not_contain_penalty_info_expectation() {
50 $penaltyinfo = get_string('gradingdetailspenalty', 'qbehaviour_adaptive', 'XXXXX');
03cefcc9 51 $penaltypattern = '/'.str_replace('XXXXX', '\\w*', preg_quote($penaltyinfo, '/')).'/';
603bd001
PS
52 return new question_no_pattern_expectation($penaltypattern);
53 }
54
55 protected function get_contains_total_penalty_expectation($penalty) {
56 $penaltyinfo = get_string('gradingdetailspenaltytotal', 'qbehaviour_adaptive',
57 format_float($penalty, $this->displayoptions->markdp));
03cefcc9 58 return new question_pattern_expectation('/'.preg_quote($penaltyinfo, '/').'/');
603bd001
PS
59 }
60
61 protected function get_does_not_contain_total_penalty_expectation() {
62 $penaltyinfo = get_string('gradingdetailspenaltytotal', 'qbehaviour_adaptive', 'XXXXX');
03cefcc9 63 $penaltypattern = '/'.str_replace('XXXXX', '\\w*', preg_quote($penaltyinfo, '/')).'/';
603bd001
PS
64 return new question_no_pattern_expectation($penaltypattern);
65 }
66
67 protected function get_contains_disregarded_info_expectation() {
68 $penaltyinfo = get_string('disregardedwithoutpenalty', 'qbehaviour_adaptive');
03cefcc9 69 return new question_pattern_expectation('/'.preg_quote($penaltyinfo, '/').'/');
603bd001
PS
70 }
71
72 protected function get_does_not_contain_disregarded_info_expectation() {
73 $penaltyinfo = get_string('disregardedwithoutpenalty', 'qbehaviour_adaptive');
03cefcc9 74 return new question_no_pattern_expectation('/'.preg_quote($penaltyinfo, '/').'/');
603bd001
PS
75 }
76
77 public function test_adaptive_multichoice() {
78
79 // Create a multiple choice, single response question.
80 $mc = test_question_maker::make_a_multichoice_single_question();
81 $mc->penalty = 0.3333333;
82 $this->start_attempt_at_question($mc, 'adaptive', 3);
83
84 $rightindex = $this->get_mc_right_answer_index($mc);
85 $wrongindex = ($rightindex + 1) % 3;
86
87 // Check the initial state.
88 $this->check_current_state(question_state::$todo);
89 $this->check_current_mark(null);
90 $this->check_current_output(
91 $this->get_contains_marked_out_of_summary(),
92 $this->get_contains_question_text_expectation($mc),
93 $this->get_contains_mc_radio_expectation(0, true, false),
94 $this->get_contains_mc_radio_expectation(1, true, false),
95 $this->get_contains_mc_radio_expectation(2, true, false),
96 $this->get_contains_submit_button_expectation(true),
97 $this->get_does_not_contain_feedback_expectation());
98
99 // Process a submit.
100 $this->process_submission(array('answer' => $wrongindex, '-submit' => 1));
101
102 // Verify.
103 $this->check_current_state(question_state::$todo);
104 $this->check_current_mark(0);
105 $this->check_current_output(
106 $this->get_contains_mark_summary(0),
107 $this->get_contains_mc_radio_expectation($wrongindex, true, true),
108 $this->get_contains_mc_radio_expectation(($wrongindex + 1) % 3, true, false),
109 $this->get_contains_mc_radio_expectation(($wrongindex + 2) % 3, true, false),
110 $this->get_contains_incorrect_expectation(),
111 $this->get_contains_penalty_info_expectation(1.00),
112 $this->get_does_not_contain_total_penalty_expectation());
113 $this->assertRegExp('/B|C/',
114 $this->quba->get_response_summary($this->slot));
115
116 // Process a change of answer to the right one, but not sumbitted.
117 $this->process_submission(array('answer' => $rightindex));
118
119 // Verify.
120 $this->check_current_state(question_state::$todo);
121 $this->check_current_mark(0);
122 $this->check_current_output(
123 $this->get_contains_mark_summary(0),
124 $this->get_contains_mc_radio_expectation($rightindex, true, true),
125 $this->get_contains_mc_radio_expectation(($rightindex + 1) % 3, true, false),
126 $this->get_contains_mc_radio_expectation(($rightindex + 2) % 3, true, false));
127 $this->assertRegExp('/B|C/',
128 $this->quba->get_response_summary($this->slot));
129
130 // Now submit the right answer.
131 $this->process_submission(array('answer' => $rightindex, '-submit' => 1));
132
133 // Verify.
134 $this->check_current_state(question_state::$complete);
135 $this->check_current_mark(3 * (1 - $mc->penalty));
136 $this->check_current_output(
137 $this->get_contains_mark_summary(3 * (1 - $mc->penalty)),
138 $this->get_contains_mc_radio_expectation($rightindex, true, true),
139 $this->get_contains_mc_radio_expectation(($rightindex + 1) % 3, true, false),
140 $this->get_contains_mc_radio_expectation(($rightindex + 2) % 3, true, false),
141 $this->get_contains_correct_expectation(),
142 $this->get_does_not_contain_penalty_info_expectation(),
143 $this->get_does_not_contain_total_penalty_expectation());
144 $this->assertEquals('A',
145 $this->quba->get_response_summary($this->slot));
146
147 // Finish the attempt.
148 $this->quba->finish_all_questions();
149
150 // Verify.
151 $this->check_current_state(question_state::$gradedright);
152 $this->check_current_mark(3 * (1 - $mc->penalty));
153 $this->check_current_output(
154 $this->get_contains_mark_summary(3 * (1 - $mc->penalty)),
155 $this->get_contains_mc_radio_expectation($rightindex, false, true),
156 $this->get_contains_mc_radio_expectation(($rightindex + 1) % 3, false, false),
157 $this->get_contains_mc_radio_expectation(($rightindex + 2) % 3, false, false),
158 $this->get_contains_correct_expectation());
159
160 // Process a manual comment.
53b8e256 161 $this->manual_grade('Not good enough!', 1, FORMAT_HTML);
603bd001
PS
162
163 // Verify.
164 $this->check_current_state(question_state::$mangrpartial);
165 $this->check_current_mark(1);
166 $this->check_current_output(
167 $this->get_contains_mark_summary(1),
03cefcc9 168 new question_pattern_expectation('/' . preg_quote('Not good enough!', '/') . '/'));
603bd001
PS
169
170 // Now change the correct answer to the question, and regrade.
171 $mc->answers[13]->fraction = -0.33333333;
172 $mc->answers[14]->fraction = 1; // We don't know which "wrong" index we chose above!
173 $mc->answers[15]->fraction = 1; // Therefore, treat answers B and C with the same score.
174 $this->quba->regrade_all_questions();
175
176 // Verify.
177 $this->check_current_state(question_state::$mangrpartial);
178 $this->check_current_mark(1);
179 $this->check_current_output(
180 $this->get_contains_mark_summary(1),
181 $this->get_contains_partcorrect_expectation());
182
183 $autogradedstep = $this->get_step($this->get_step_count() - 2);
184 $this->assertEquals($autogradedstep->get_fraction(), 1, '', 0.0000001);
185 }
186
187 public function test_adaptive_multichoice2() {
188
189 // Create a multiple choice, multiple response question.
190 $mc = test_question_maker::make_a_multichoice_multi_question();
191 $mc->penalty = 0.3333333;
192 $mc->shuffleanswers = 0;
193 $this->start_attempt_at_question($mc, 'adaptive', 2);
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_submit_button_expectation(true),
202 $this->get_does_not_contain_feedback_expectation());
203
204 // Process a submit.
205 $this->process_submission(array('choice0' => 1, 'choice2' => 1, '-submit' => 1));
206
207 // Verify.
208 $this->check_current_state(question_state::$complete);
209 $this->check_current_mark(2);
210 $this->check_current_output(
211 $this->get_contains_mark_summary(2),
212 $this->get_contains_submit_button_expectation(true),
213 $this->get_contains_correct_expectation(),
214 $this->get_does_not_contain_penalty_info_expectation(),
215 $this->get_does_not_contain_total_penalty_expectation());
216
217 // Save the same correct answer again. Should not do anything.
218 $numsteps = $this->get_step_count();
219 $this->process_submission(array('choice0' => 1, 'choice2' => 1));
220
221 // Verify.
222 $this->check_step_count($numsteps);
223 $this->check_current_mark(2);
224 $this->check_current_state(question_state::$complete);
225
226 // Finish the attempt.
227 $this->quba->finish_all_questions();
228
229 // Verify.
230 $this->check_step_count($numsteps + 1);
231 $this->check_current_state(question_state::$gradedright);
232 $this->check_current_mark(2);
233 $this->check_current_output(
234 $this->get_contains_mark_summary(2),
81e47a35 235 $this->get_does_not_contain_submit_button_expectation(),
603bd001
PS
236 $this->get_contains_correct_expectation());
237 }
238
239 public function test_adaptive_shortanswer_partially_right() {
240
d56ab3b9 241 // Create a short answer question.
603bd001
PS
242 $sa = test_question_maker::make_question('shortanswer');
243 $this->start_attempt_at_question($sa, 'adaptive');
244
245 // Check the initial state.
246 $this->check_current_state(question_state::$todo);
247 $this->check_current_mark(null);
d56ab3b9
JMV
248 $this->render();
249 $this->check_output_does_not_contain_text_input_with_class('answer', 'correct');
250 $this->check_output_does_not_contain_text_input_with_class('answer', 'partiallycorrect');
251 $this->check_output_does_not_contain_text_input_with_class('answer', 'incorrect');
603bd001
PS
252 $this->check_current_output(
253 $this->get_contains_marked_out_of_summary(),
254 $this->get_contains_submit_button_expectation(true),
255 $this->get_does_not_contain_feedback_expectation());
256
257 // Submit a partially correct answer.
258 $this->process_submission(array('-submit' => 1, 'answer' => 'toad'));
259
260 // Verify.
261 $this->check_current_state(question_state::$todo);
262 $this->check_current_mark(0.8);
d56ab3b9
JMV
263 $this->render();
264 $this->check_output_contains_text_input_with_class('answer', 'partiallycorrect');
603bd001
PS
265 $this->check_current_output(
266 $this->get_contains_mark_summary(0.8),
267 $this->get_contains_submit_button_expectation(true),
268 $this->get_contains_partcorrect_expectation(),
269 $this->get_contains_penalty_info_expectation(0.33),
270 $this->get_does_not_contain_total_penalty_expectation(),
271 $this->get_does_not_contain_validation_error_expectation());
272
273 // Submit an incorrect answer.
274 $this->process_submission(array('-submit' => 1, 'answer' => 'bumblebee'));
275
276 // Verify.
277 $this->check_current_state(question_state::$todo);
278 $this->check_current_mark(0.8);
d56ab3b9
JMV
279 $this->render();
280 $this->check_output_contains_text_input_with_class('answer', 'incorrect');
603bd001
PS
281 $this->check_current_output(
282 $this->get_contains_mark_summary(0.8),
283 $this->get_contains_submit_button_expectation(true),
284 $this->get_contains_incorrect_expectation(),
285 $this->get_contains_penalty_info_expectation(0.33),
286 $this->get_contains_total_penalty_expectation(0.67),
287 $this->get_does_not_contain_validation_error_expectation());
288
289 // Submit a correct answer.
290 $this->process_submission(array('-submit' => 1, 'answer' => 'frog'));
291
292 // Verify.
293 $this->check_current_state(question_state::$complete);
294 $this->check_current_mark(0.8);
d56ab3b9
JMV
295 $this->render();
296 $this->check_output_contains_text_input_with_class('answer', 'correct');
603bd001
PS
297 $this->check_current_output(
298 $this->get_contains_mark_summary(0.8),
299 $this->get_contains_submit_button_expectation(true),
300 $this->get_contains_correct_expectation(),
301 $this->get_does_not_contain_penalty_info_expectation(),
302 $this->get_does_not_contain_total_penalty_expectation(),
303 $this->get_does_not_contain_validation_error_expectation());
304
305 // Finish the attempt.
306 $this->quba->finish_all_questions();
307
308 // Verify.
309 $this->check_current_state(question_state::$gradedright);
310 $this->check_current_mark(0.8);
311 $this->check_current_output(
312 $this->get_contains_mark_summary(0.8),
81e47a35 313 $this->get_does_not_contain_submit_button_expectation(),
603bd001
PS
314 $this->get_contains_correct_expectation(),
315 $this->get_does_not_contain_validation_error_expectation());
316 }
317
318 public function test_adaptive_shortanswer_wrong_right_wrong() {
319
d56ab3b9 320 // Create a short answer question.
603bd001
PS
321 $sa = test_question_maker::make_question('shortanswer');
322 $this->start_attempt_at_question($sa, 'adaptive', 6);
323
324 // Check the initial state.
325 $this->check_current_state(question_state::$todo);
326 $this->check_current_mark(null);
327 $this->check_current_output(
328 $this->get_contains_marked_out_of_summary(),
329 $this->get_contains_submit_button_expectation(true),
330 $this->get_does_not_contain_feedback_expectation());
331
332 // Submit a wrong answer.
333 $this->process_submission(array('-submit' => 1, 'answer' => 'hippopotamus'));
334
335 // Verify.
336 $this->check_current_state(question_state::$todo);
337 $this->check_current_mark(0);
338 $this->check_current_output(
339 $this->get_contains_mark_summary(0),
340 $this->get_contains_submit_button_expectation(true),
341 $this->get_contains_incorrect_expectation(),
342 $this->get_contains_penalty_info_expectation(2.00),
343 $this->get_does_not_contain_total_penalty_expectation(),
344 $this->get_does_not_contain_validation_error_expectation());
345
346 // Submit the same wrong answer again. Nothing should change.
347 $this->process_submission(array('-submit' => 1, 'answer' => 'hippopotamus'));
348
349 // Verify.
350 $this->check_current_state(question_state::$todo);
351 $this->check_current_mark(0);
352 $this->check_current_output(
353 $this->get_contains_mark_summary(0),
354 $this->get_contains_submit_button_expectation(true),
355 $this->get_contains_incorrect_expectation(),
356 $this->get_contains_penalty_info_expectation(2.00),
357 $this->get_does_not_contain_total_penalty_expectation(),
358 $this->get_does_not_contain_validation_error_expectation());
359
360 // Submit a correct answer.
361 $this->process_submission(array('-submit' => 1, 'answer' => 'frog'));
362
363 // Verify.
364 $this->check_current_state(question_state::$complete);
365 $this->check_current_mark(4.00);
366 $this->check_current_output(
367 $this->get_contains_mark_summary(4.00),
368 $this->get_contains_submit_button_expectation(true),
369 $this->get_contains_correct_expectation(),
370 $this->get_does_not_contain_penalty_info_expectation(),
371 $this->get_does_not_contain_total_penalty_expectation(),
372 $this->get_does_not_contain_validation_error_expectation());
373
374 // Submit another incorrect answer.
375 $this->process_submission(array('-submit' => 1, 'answer' => 'bumblebee'));
376
377 // Verify.
378 $this->check_current_state(question_state::$complete);
379 $this->check_current_mark(4.00);
380 $this->check_current_output(
381 $this->get_contains_mark_summary(4.00),
382 $this->get_contains_submit_button_expectation(true),
383 $this->get_contains_incorrect_expectation(),
384 $this->get_does_not_contain_penalty_info_expectation(),
385 $this->get_does_not_contain_total_penalty_expectation(),
386 $this->get_does_not_contain_validation_error_expectation());
387
388 // Finish the attempt.
389 $this->quba->finish_all_questions();
390
391 // Verify.
392 $this->check_current_state(question_state::$gradedwrong);
393 $this->check_current_mark(4.00);
394 $this->check_current_output(
395 $this->get_contains_mark_summary(4.00),
81e47a35 396 $this->get_does_not_contain_submit_button_expectation(),
603bd001
PS
397 $this->get_contains_incorrect_expectation(),
398 $this->get_does_not_contain_validation_error_expectation());
399 }
400
401 public function test_adaptive_shortanswer_invalid_after_complete() {
402
d56ab3b9 403 // Create a short answer question.
603bd001
PS
404 $sa = test_question_maker::make_question('shortanswer');
405 $this->start_attempt_at_question($sa, 'adaptive');
406
407 // Check the initial state.
408 $this->check_current_state(question_state::$todo);
409 $this->check_current_mark(null);
410 $this->check_current_output(
411 $this->get_contains_marked_out_of_summary(),
412 $this->get_contains_submit_button_expectation(true),
413 $this->get_does_not_contain_feedback_expectation());
414
415 // Submit a wrong answer.
416 $this->process_submission(array('-submit' => 1, 'answer' => 'hippopotamus'));
417
418 // Verify.
419 $this->check_current_state(question_state::$todo);
420 $this->check_current_mark(0);
421 $this->check_current_output(
422 $this->get_contains_mark_summary(0),
423 $this->get_contains_submit_button_expectation(true),
424 $this->get_contains_incorrect_expectation(),
425 $this->get_contains_penalty_info_expectation(0.33),
426 $this->get_does_not_contain_total_penalty_expectation(),
427 $this->get_does_not_contain_validation_error_expectation());
428
429 // Submit a correct answer.
430 $this->process_submission(array('-submit' => 1, 'answer' => 'frog'));
431
432 // Verify.
433 $this->check_current_state(question_state::$complete);
434 $this->check_current_mark(0.66666667);
435 $this->check_current_output(
436 $this->get_contains_mark_summary(0.67),
437 $this->get_contains_submit_button_expectation(true),
438 $this->get_contains_correct_expectation(),
439 $this->get_does_not_contain_penalty_info_expectation(),
440 $this->get_does_not_contain_total_penalty_expectation(),
441 $this->get_does_not_contain_validation_error_expectation());
442
443 // Submit an empty answer.
444 $this->process_submission(array('-submit' => 1, 'answer' => ''));
445
446 // Verify.
447 $this->check_current_state(question_state::$invalid);
448 $this->check_current_mark(0.66666667);
449 $this->check_current_output(
450 $this->get_contains_mark_summary(0.67),
451 $this->get_contains_submit_button_expectation(true),
452 $this->get_does_not_contain_penalty_info_expectation(),
453 $this->get_does_not_contain_total_penalty_expectation(),
454 $this->get_contains_validation_error_expectation());
455
456 // Submit another wrong answer.
457 $this->process_submission(array('-submit' => 1, 'answer' => 'bumblebee'));
458
459 // Verify.
460 $this->check_current_state(question_state::$complete);
461 $this->check_current_mark(0.66666667);
462 $this->check_current_output(
463 $this->get_contains_mark_summary(0.67),
464 $this->get_contains_submit_button_expectation(true),
465 $this->get_contains_incorrect_expectation(),
466 $this->get_does_not_contain_penalty_info_expectation(),
467 $this->get_does_not_contain_total_penalty_expectation(),
468 $this->get_does_not_contain_validation_error_expectation());
469
470 // Finish the attempt.
471 $this->quba->finish_all_questions();
472
473 // Verify.
474 $this->check_current_state(question_state::$gradedwrong);
475 $this->check_current_mark(0.66666667);
476 $this->check_current_output(
477 $this->get_contains_mark_summary(0.67),
81e47a35 478 $this->get_does_not_contain_submit_button_expectation(),
603bd001
PS
479 $this->get_contains_incorrect_expectation(),
480 $this->get_does_not_contain_validation_error_expectation());
481 }
482
483 public function test_adaptive_shortanswer_zero_penalty() {
484
d56ab3b9 485 // Create a short answer question.
603bd001 486 $sa = test_question_maker::make_question('shortanswer');
d56ab3b9 487 // Disable penalties for this question.
603bd001
PS
488 $sa->penalty = 0;
489 $this->start_attempt_at_question($sa, 'adaptive');
490
491 // Check the initial state.
492 $this->check_current_state(question_state::$todo);
493 $this->check_current_mark(null);
494 $this->check_current_output(
495 $this->get_contains_marked_out_of_summary(),
496 $this->get_contains_submit_button_expectation(true),
497 $this->get_does_not_contain_feedback_expectation());
498
499 // Submit a wrong answer.
500 $this->process_submission(array('-submit' => 1, 'answer' => 'hippopotamus'));
501
502 // Verify.
503 $this->check_current_state(question_state::$todo);
504 $this->check_current_mark(0);
505 $this->check_current_output(
506 $this->get_contains_mark_summary(0),
507 $this->get_contains_submit_button_expectation(true),
508 $this->get_contains_incorrect_expectation(),
509 $this->get_does_not_contain_penalty_info_expectation(),
510 $this->get_does_not_contain_total_penalty_expectation(),
511 $this->get_does_not_contain_validation_error_expectation());
512
513 // Submit a correct answer.
514 $this->process_submission(array('-submit' => 1, 'answer' => 'frog'));
515
516 // Verify.
517 $this->check_current_state(question_state::$complete);
518 $this->check_current_mark(1.0);
519 $this->check_current_output(
520 $this->get_contains_mark_summary(1.0),
521 $this->get_contains_submit_button_expectation(true),
522 $this->get_contains_correct_expectation(),
523 $this->get_does_not_contain_penalty_info_expectation(),
524 $this->get_does_not_contain_total_penalty_expectation(),
525 $this->get_does_not_contain_validation_error_expectation());
526
527 // Finish the attempt.
528 $this->quba->finish_all_questions();
529
530 // Verify.
531 $this->check_current_state(question_state::$gradedright);
532 $this->check_current_mark(1.0);
533 $this->check_current_output(
534 $this->get_contains_mark_summary(1.0),
81e47a35 535 $this->get_does_not_contain_submit_button_expectation(),
603bd001
PS
536 $this->get_contains_correct_expectation(),
537 $this->get_does_not_contain_validation_error_expectation());
538 }
539
540 public function test_adaptive_shortanswer_try_to_submit_blank() {
541
542 // Create a short answer question with correct answer true.
543 $sa = test_question_maker::make_question('shortanswer');
544 $this->start_attempt_at_question($sa, 'adaptive');
545
546 // Check the initial state.
547 $this->check_current_state(question_state::$todo);
548 $this->check_current_mark(null);
549 $this->check_current_output(
550 $this->get_contains_marked_out_of_summary(),
551 $this->get_contains_submit_button_expectation(true),
552 $this->get_does_not_contain_feedback_expectation());
553
554 // Submit with blank answer.
555 $this->process_submission(array('-submit' => 1, 'answer' => ''));
556
557 // Verify.
558 $this->check_current_state(question_state::$invalid);
559 $this->check_current_mark(null);
560 $this->check_current_output(
561 $this->get_contains_marked_out_of_summary(),
562 $this->get_contains_submit_button_expectation(true),
563 $this->get_does_not_contain_correctness_expectation(),
564 $this->get_does_not_contain_penalty_info_expectation(),
565 $this->get_does_not_contain_total_penalty_expectation(),
566 $this->get_contains_validation_error_expectation(),
567 $this->get_contains_disregarded_info_expectation());
568 $this->assertNull($this->quba->get_response_summary($this->slot));
569
570 // Now get it wrong.
571 $this->process_submission(array('-submit' => 1, 'answer' => 'toad'));
572
573 // Verify.
574 $this->check_current_state(question_state::$todo);
575 $this->check_current_mark(0.8);
576 $this->check_current_output(
577 $this->get_contains_mark_summary(0.8),
578 $this->get_contains_submit_button_expectation(true),
579 $this->get_contains_partcorrect_expectation(),
580 $this->get_contains_penalty_info_expectation(0.33),
581 $this->get_does_not_contain_total_penalty_expectation(),
582 $this->get_does_not_contain_validation_error_expectation());
583
584 // Now submit blank again.
585 $this->process_submission(array('-submit' => 1, 'answer' => ''));
586
587 // Verify.
588 $this->check_current_state(question_state::$invalid);
589 $this->check_current_mark(0.8);
590 $this->check_current_output(
591 $this->get_contains_mark_summary(0.8),
592 $this->get_contains_submit_button_expectation(true),
593 $this->get_does_not_contain_correctness_expectation(),
594 $this->get_does_not_contain_penalty_info_expectation(),
595 $this->get_does_not_contain_total_penalty_expectation(),
596 $this->get_contains_validation_error_expectation());
597 }
598
599 public function test_adaptive_numerical() {
600
d56ab3b9 601 // Create a numerical question.
603bd001
PS
602 $sa = test_question_maker::make_question('numerical', 'pi');
603 $this->start_attempt_at_question($sa, 'adaptive');
604
605 // Check the initial state.
606 $this->check_current_state(question_state::$todo);
607 $this->check_current_mark(null);
608 $this->check_current_output(
609 $this->get_contains_marked_out_of_summary(),
610 $this->get_contains_submit_button_expectation(true),
611 $this->get_does_not_contain_feedback_expectation());
612
613 // Submit the correct answer.
614 $this->process_submission(array('-submit' => 1, 'answer' => '3.14'));
615
616 // Verify.
617 $this->check_current_state(question_state::$complete);
618 $this->check_current_mark(1);
619 $this->check_current_output(
620 $this->get_contains_mark_summary(1),
621 $this->get_contains_submit_button_expectation(true),
622 $this->get_contains_correct_expectation(),
623 $this->get_does_not_contain_penalty_info_expectation(),
624 $this->get_does_not_contain_total_penalty_expectation(),
625 $this->get_does_not_contain_validation_error_expectation());
626
627 // Submit an incorrect answer.
628 $this->process_submission(array('-submit' => 1, 'answer' => '-5'));
629
630 // Verify.
631 $this->check_current_state(question_state::$complete);
632 $this->check_current_mark(1);
633 $this->check_current_output(
634 $this->get_contains_mark_summary(1),
635 $this->get_contains_submit_button_expectation(true),
636 $this->get_contains_incorrect_expectation(),
637 $this->get_does_not_contain_penalty_info_expectation(),
638 $this->get_does_not_contain_total_penalty_expectation(),
639 $this->get_does_not_contain_validation_error_expectation());
640
641 // Finish the attempt.
642 $this->quba->finish_all_questions();
643
644 // Verify.
645 $this->check_current_state(question_state::$gradedwrong);
646 $this->check_current_mark(1);
647 $this->check_current_output(
648 $this->get_contains_mark_summary(1),
81e47a35 649 $this->get_does_not_contain_submit_button_expectation(),
603bd001
PS
650 $this->get_contains_incorrect_expectation(),
651 $this->get_does_not_contain_validation_error_expectation());
652 }
653
654 public function test_adaptive_numerical_invalid() {
655
d56ab3b9 656 // Create a numerical question.
603bd001
PS
657 $numq = test_question_maker::make_question('numerical', 'pi');
658 $numq->penalty = 0.1;
659 $this->start_attempt_at_question($numq, 'adaptive');
660
661 // Check the initial state.
662 $this->check_current_state(question_state::$todo);
663 $this->check_current_mark(null);
664 $this->check_current_output(
665 $this->get_contains_marked_out_of_summary(),
666 $this->get_contains_submit_button_expectation(true),
667 $this->get_does_not_contain_feedback_expectation());
668
669 // Submit a non-numerical answer.
670 $this->process_submission(array('-submit' => 1, 'answer' => 'Pi'));
671
672 // Verify.
673 $this->check_current_state(question_state::$invalid);
674 $this->check_current_mark(null);
675 $this->check_current_output(
676 $this->get_contains_marked_out_of_summary(1),
677 $this->get_contains_submit_button_expectation(true),
678 $this->get_does_not_contain_correctness_expectation(),
679 $this->get_does_not_contain_penalty_info_expectation(),
680 $this->get_does_not_contain_total_penalty_expectation(),
681 $this->get_contains_validation_error_expectation(),
682 $this->get_contains_disregarded_info_expectation());
683
684 // Submit an incorrect answer.
685 $this->process_submission(array('-submit' => 1, 'answer' => '-5'));
686
687 // Verify.
688 $this->check_current_state(question_state::$todo);
689 $this->check_current_mark(0);
690 $this->check_current_output(
691 $this->get_contains_mark_summary(0),
692 $this->get_contains_submit_button_expectation(true),
693 $this->get_contains_incorrect_expectation(),
694 $this->get_contains_penalty_info_expectation(0.1),
695 $this->get_does_not_contain_total_penalty_expectation(),
696 $this->get_does_not_contain_validation_error_expectation(),
697 $this->get_does_not_contain_disregarded_info_expectation());
698
699 // Submit another non-numerical answer.
700 $this->process_submission(array('-submit' => 1, 'answer' => 'Pi*2'));
701
702 // Verify.
703 $this->check_current_state(question_state::$invalid);
704 $this->check_current_mark(0);
705 $this->check_current_output(
706 $this->get_contains_mark_summary(0),
707 $this->get_contains_submit_button_expectation(true),
708 $this->get_does_not_contain_correctness_expectation(),
709 $this->get_does_not_contain_penalty_info_expectation(),
710 $this->get_does_not_contain_total_penalty_expectation(),
711 $this->get_contains_validation_error_expectation(),
712 $this->get_contains_disregarded_info_expectation());
713
714 // Submit the correct answer.
715 $this->process_submission(array('-submit' => 1, 'answer' => '3.14'));
716
717 // Verify.
718 $this->check_current_state(question_state::$complete);
719 $this->check_current_mark(0.9);
720 $this->check_current_output(
721 $this->get_contains_mark_summary(0.9),
722 $this->get_contains_submit_button_expectation(true),
723 $this->get_contains_correct_expectation(),
724 $this->get_does_not_contain_penalty_info_expectation(),
725 $this->get_does_not_contain_total_penalty_expectation(),
726 $this->get_does_not_contain_validation_error_expectation(),
727 $this->get_does_not_contain_disregarded_info_expectation());
728
729 // Submit another non-numerical answer.
730 $this->process_submission(array('-submit' => 1, 'answer' => 'Pi/3'));
731
732 // Verify.
733 $this->check_current_state(question_state::$invalid);
734 $this->check_current_mark(0.9);
735 $this->check_current_output(
736 $this->get_contains_mark_summary(0.9),
737 $this->get_contains_submit_button_expectation(true),
738 $this->get_does_not_contain_correctness_expectation(),
739 $this->get_does_not_contain_penalty_info_expectation(),
740 $this->get_does_not_contain_total_penalty_expectation(),
741 $this->get_contains_validation_error_expectation(),
742 $this->get_contains_disregarded_info_expectation());
743
744 // Finish the attempt.
745 $this->quba->finish_all_questions();
746
747 // Verify.
748 $this->check_current_state(question_state::$gradedwrong);
749 $this->check_current_mark(0.9);
750 $this->check_current_output(
751 $this->get_contains_mark_summary(0.9),
81e47a35 752 $this->get_does_not_contain_submit_button_expectation(),
603bd001
PS
753 $this->get_contains_incorrect_expectation(),
754 $this->get_does_not_contain_validation_error_expectation(),
755 $this->get_does_not_contain_disregarded_info_expectation());
756 }
d56ab3b9
JMV
757
758 public function test_adaptive_multianswer() {
759
760 // Create a multianswer question.
761 $q = test_question_maker::make_question('multianswer', 'twosubq');
762 // To simplify testing, multichoice subquestion's answers are not shuffled.
763 $q->subquestions[2]->shuffleanswers = 0;
764 $choices = array('' => '', '0' => 'Bow-wow', '1' => 'Wiggly worm', '2' => 'Pussy-cat');
765
766 $this->start_attempt_at_question($q, 'adaptive', 12);
767
768 // Check the initial state.
769 $this->check_current_state(question_state::$todo);
770 $this->check_current_mark(null);
771 $this->assertEquals('adaptive',
772 $this->quba->get_question_attempt($this->slot)->get_behaviour_name());
773 $this->render();
774 $this->check_output_contains_text_input('sub1_answer', '', true);
775 $this->check_output_does_not_contain_text_input_with_class('sub1_answer', 'correct');
776 $this->check_output_does_not_contain_text_input_with_class('sub1_answer', 'partiallycorrect');
777 $this->check_output_does_not_contain_text_input_with_class('sub1_answer', 'incorrect');
778 $this->check_current_output(
779 $this->get_contains_marked_out_of_summary(),
780 $this->get_contains_select_expectation('sub2_answer', $choices, null, true),
781 $this->get_contains_submit_button_expectation(true),
782 $this->get_does_not_contain_validation_error_expectation(),
783 $this->get_does_not_contain_feedback_expectation());
784
785 // Submit an invalid response.
786 $this->process_submission(array('sub1_answer' => '', 'sub2_answer' => 1, '-submit' => 1));
787
788 // Verify.
789 $this->check_current_state(question_state::$invalid);
790 $this->check_current_mark(null);
791 $this->check_output_contains_text_input('sub1_answer', '', true);
792 $this->check_current_output(
793 $this->get_contains_select_expectation('sub2_answer', $choices, 1, true),
794 $this->get_contains_submit_button_expectation(true),
795 $this->get_does_not_contain_penalty_info_expectation(),
796 $this->get_does_not_contain_total_penalty_expectation(),
797 $this->get_contains_disregarded_info_expectation());
798
799 // Check that extract responses will return the reset data.
800 $prefix = $this->quba->get_field_prefix($this->slot);
801 $this->assertEquals(array('sub2_answer' => 1),
802 $this->quba->extract_responses($this->slot, array($prefix . 'sub2_answer' => 1)));
803
804 // Submit an incorrect response.
805 $this->process_submission(array('sub1_answer' => 'Dog',
806 'sub2_answer' => 1, '-submit' => 1));
807
808 // Verify.
809 $this->check_current_state(question_state::$todo);
810 $this->check_current_mark(0);
811 $this->render();
812 $this->check_output_contains_text_input('sub1_answer', 'Dog', true);
813 $this->check_output_contains_text_input_with_class('sub1_answer', 'incorrect');
814 $this->check_current_output(
815 $this->get_contains_mark_summary(0),
816 $this->get_contains_select_expectation('sub2_answer', $choices, 1, true),
817 $this->get_contains_submit_button_expectation(true),
818 $this->get_contains_incorrect_expectation(),
819 $this->get_contains_penalty_info_expectation(4.00),
820 $this->get_does_not_contain_validation_error_expectation());
821
822 // Submit the right answer.
823 $this->process_submission(array('sub1_answer' => 'Owl', 'sub2_answer' => 2, '-submit' => 1));
824
825 // Verify.
826 $this->check_current_state(question_state::$complete);
827 $this->check_current_mark(8.00);
828 $this->render();
829 $this->check_output_contains_text_input('sub1_answer', 'Owl', true);
830 $this->check_output_contains_text_input_with_class('sub1_answer', 'correct');
831 $this->check_current_output(
832 $this->get_contains_select_expectation('sub2_answer', $choices, '2', true),
833 $this->get_contains_mark_summary(8.00),
834 $this->get_contains_submit_button_expectation(true),
835 $this->get_contains_correct_expectation(),
836 $this->get_does_not_contain_penalty_info_expectation(),
837 $this->get_does_not_contain_total_penalty_expectation(),
838 $this->get_does_not_contain_validation_error_expectation());
839
840 // Finish the attempt.
841 $this->quba->finish_all_questions();
842
843 // Verify.
844 $this->check_current_state(question_state::$gradedright);
845 $this->check_current_mark(8.00);
846 $this->render();
847 $this->check_output_contains_text_input('sub1_answer', 'Owl', false);
848 $this->check_output_contains_text_input_with_class('sub1_answer', 'correct');
849 $this->check_current_output(
850 $this->get_contains_mark_summary(8.00),
81e47a35 851 $this->get_does_not_contain_submit_button_expectation(),
d56ab3b9
JMV
852 $this->get_contains_correct_expectation(),
853 $this->get_does_not_contain_validation_error_expectation());
854 }
603bd001 855}