Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

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