Proyectos de Subversion Moodle

Rev

Rev 11 | | 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 qtype_multianswer;
18
 
19
use qtype_multianswer;
20
use question_bank;
21
use question_display_options;
22
use question_hint_with_parts;
23
use question_state;
24
use test_question_maker;
25
 
26
defined('MOODLE_INTERNAL') || die();
27
 
28
global $CFG;
29
require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
30
require_once($CFG->dirroot . '/question/type/multianswer/questiontype.php');
31
 
32
 
33
/**
34
 * Unit tests for the multianswer question type.
35
 *
36
 * @package    qtype_multianswer
37
 * @copyright  2011 The Open University
38
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39
 */
1441 ariadna 40
final class walkthrough_test extends \qbehaviour_walkthrough_test_base {
1 efrain 41
 
42
    protected function get_contains_subq_status(question_state $state) {
43
        return new \question_pattern_expectation('~' .
44
                preg_quote($state->default_string(true), '~') . '~');
45
    }
46
 
11 efrain 47
    public function test_deferred_feedback(): void {
1 efrain 48
 
49
        // Create a multianswer question.
50
        $q = \test_question_maker::make_question('multianswer', 'fourmc');
51
        $this->start_attempt_at_question($q, 'deferredfeedback', 4);
52
 
53
        // Check the initial state.
54
        $this->check_current_state(question_state::$todo);
55
        $this->check_current_mark(null);
56
        $this->check_current_output(
57
                $this->get_contains_marked_out_of_summary(),
58
                $this->get_does_not_contain_feedback_expectation(),
59
                $this->get_does_not_contain_validation_error_expectation());
60
 
61
        // Save in incomplete answer.
62
        $this->process_submission(array('sub1_answer' => '1', 'sub2_answer' => '',
63
                'sub3_answer' => '', 'sub4_answer' => ''));
64
 
65
        // Verify.
66
        $this->check_current_state(question_state::$invalid);
67
        $this->check_current_mark(null);
68
        $this->check_current_output(
69
                $this->get_contains_marked_out_of_summary(),
70
                $this->get_does_not_contain_feedback_expectation(),
71
                $this->get_contains_validation_error_expectation());
72
 
73
        // Save a partially correct answer.
74
        $this->process_submission(array('sub1_answer' => '1', 'sub2_answer' => '1',
75
                'sub3_answer' => '1', 'sub4_answer' => '1'));
76
 
77
        // Verify.
78
        $this->check_current_state(question_state::$complete);
79
        $this->check_current_mark(null);
80
        $this->check_current_output(
81
                $this->get_contains_marked_out_of_summary(),
82
                $this->get_does_not_contain_feedback_expectation(),
83
                $this->get_does_not_contain_validation_error_expectation());
84
 
85
        // Now submit all and finish.
86
        $this->finish();
87
 
88
        // Verify.
89
        $this->check_current_state(question_state::$gradedpartial);
90
        $this->check_current_mark(2);
91
        $this->check_current_output(
92
                $this->get_contains_mark_summary(2),
93
                $this->get_contains_partcorrect_expectation(),
94
                $this->get_does_not_contain_validation_error_expectation());
95
    }
96
 
11 efrain 97
    public function test_deferred_feedback_numericalzero_not_answered(): void {
1 efrain 98
        // Tests the situation found in MDL-35370.
99
 
100
        // Create a multianswer question with one numerical subquestion, right answer zero.
101
        $q = \test_question_maker::make_question('multianswer', 'numericalzero');
102
        $this->start_attempt_at_question($q, 'deferredfeedback', 1);
103
 
104
        // Check the initial state.
105
        $this->check_current_state(question_state::$todo);
106
        $this->check_current_mark(null);
107
        $this->check_current_output(
108
                $this->get_contains_marked_out_of_summary(),
109
                $this->get_does_not_contain_feedback_expectation(),
110
                $this->get_does_not_contain_validation_error_expectation());
111
 
112
        // Now submit all and finish.
113
        $this->finish();
114
 
115
        // Verify.
116
        $this->check_current_state(question_state::$gaveup);
117
        $this->check_current_mark(null);
118
        $this->check_current_output(
119
                $this->get_contains_marked_out_of_summary(),
120
                new \question_pattern_expectation('~<input[^>]* class="[^"]*incorrect[^"]*" [^>]*/>~'),
121
                $this->get_contains_subq_status(question_state::$gaveup),
122
                $this->get_does_not_contain_validation_error_expectation());
123
    }
124
 
11 efrain 125
    public function test_deferred_feedback_numericalzero_0_answer(): void {
1 efrain 126
        // Tests the situation found in MDL-35370.
127
 
128
        // Create a multianswer question with one numerical subquestion, right answer zero.
129
        $q = \test_question_maker::make_question('multianswer', 'numericalzero');
130
        $this->start_attempt_at_question($q, 'deferredfeedback', 1);
131
 
132
        // Check the initial state.
133
        $this->check_current_state(question_state::$todo);
134
        $this->check_current_mark(null);
135
        $this->check_current_output(
136
                $this->get_contains_marked_out_of_summary(),
137
                $this->get_does_not_contain_feedback_expectation(),
138
                $this->get_does_not_contain_validation_error_expectation());
139
 
140
        // Save a the correct answer.
141
        $this->process_submission(array('sub1_answer' => '0'));
142
 
143
        // Verify.
144
        $this->check_current_state(question_state::$complete);
145
        $this->check_current_mark(null);
146
        $this->check_current_output(
147
                $this->get_contains_marked_out_of_summary(),
148
                $this->get_does_not_contain_feedback_expectation(),
149
                $this->get_does_not_contain_validation_error_expectation());
150
 
151
        // Now submit all and finish.
152
        $this->finish();
153
 
154
        // Verify.
155
        $this->check_current_state(question_state::$gradedright);
156
        $this->check_current_mark(1);
157
        $this->check_current_output(
158
                $this->get_contains_mark_summary(1),
159
                $this->get_contains_correct_expectation(),
160
                $this->get_contains_subq_status(question_state::$gradedright),
161
                $this->get_does_not_contain_validation_error_expectation());
162
    }
163
 
11 efrain 164
    public function test_deferred_feedback_numericalzero_0_wrong(): void {
1 efrain 165
        // Tests the situation found in MDL-35370.
166
 
167
        // Create a multianswer question with one numerical subquestion, right answer zero.
168
        $q = \test_question_maker::make_question('multianswer', 'numericalzero');
169
        $this->start_attempt_at_question($q, 'deferredfeedback', 1);
170
 
171
        // Check the initial state.
172
        $this->check_current_state(question_state::$todo);
173
        $this->check_current_mark(null);
174
        $this->check_current_output(
175
                $this->get_contains_marked_out_of_summary(),
176
                $this->get_does_not_contain_feedback_expectation(),
177
                $this->get_does_not_contain_validation_error_expectation());
178
 
179
        // Save a the correct answer.
180
        $this->process_submission(array('sub1_answer' => '42'));
181
 
182
        // Verify.
183
        $this->check_current_state(question_state::$complete);
184
        $this->check_current_mark(null);
185
        $this->check_current_output(
186
                $this->get_contains_marked_out_of_summary(),
187
                $this->get_does_not_contain_feedback_expectation(),
188
                $this->get_does_not_contain_validation_error_expectation());
189
 
190
        // Now submit all and finish.
191
        $this->finish();
192
 
193
        // Verify.
194
        $this->check_current_state(question_state::$gradedwrong);
195
        $this->check_current_mark(0);
196
        $this->check_current_output(
197
                $this->get_contains_mark_summary(0),
198
                $this->get_contains_incorrect_expectation(),
199
                $this->get_contains_subq_status(question_state::$gradedwrong),
200
                $this->get_does_not_contain_validation_error_expectation());
201
    }
202
 
11 efrain 203
    public function test_interactive_feedback(): void {
1 efrain 204
 
205
        // Create a multianswer question.
206
        $q = \test_question_maker::make_question('multianswer', 'fourmc');
207
        $q->hints = array(
208
            new question_hint_with_parts(11, 'This is the first hint.', FORMAT_HTML, false, true),
209
            new question_hint_with_parts(12, 'This is the second hint.', FORMAT_HTML, true, true),
210
        );
211
        $choices = array('0' => 'California', '1' => 'Arizona');
212
 
213
        $this->start_attempt_at_question($q, 'interactive', 4);
214
 
215
        // Check the initial state.
216
        $this->check_current_state(question_state::$todo);
217
        $this->check_current_mark(null);
218
        $this->assertEquals('interactivecountback',
219
                $this->quba->get_question_attempt($this->slot)->get_behaviour_name());
220
        $this->check_current_output(
221
                $this->get_contains_marked_out_of_summary(),
222
                $this->get_contains_submit_button_expectation(true),
223
                $this->get_does_not_contain_validation_error_expectation(),
224
                $this->get_does_not_contain_feedback_expectation(),
225
                $this->get_tries_remaining_expectation(3),
226
                $this->get_does_not_contain_num_parts_correct(),
227
                $this->get_no_hint_visible_expectation());
228
        $this->check_output_contains_selectoptions(
229
                $this->get_contains_select_expectation('sub1_answer', $choices, null, true),
230
                $this->get_contains_select_expectation('sub2_answer', $choices, null, true),
231
                $this->get_contains_select_expectation('sub3_answer', $choices, null, true),
232
                $this->get_contains_select_expectation('sub4_answer', $choices, null, true));
233
 
234
        // Submit a completely wrong response.
235
        $this->process_submission(array('sub1_answer' => '1', 'sub2_answer' => '0',
236
                'sub3_answer' => '1', 'sub4_answer' => '0', '-submit' => 1));
237
 
238
        // Verify.
239
        $this->check_current_state(question_state::$todo);
240
        $this->check_current_mark(null);
241
        $this->check_current_output(
242
                $this->get_does_not_contain_num_parts_correct(),
243
                $this->get_contains_hidden_expectation(
244
                        $this->quba->get_field_prefix($this->slot) . 'sub1_answer', ''),
245
                $this->get_contains_hidden_expectation(
246
                        $this->quba->get_field_prefix($this->slot) . 'sub2_answer', ''),
247
                $this->get_contains_hidden_expectation(
248
                        $this->quba->get_field_prefix($this->slot) . 'sub3_answer', ''),
249
                $this->get_contains_hidden_expectation(
250
                        $this->quba->get_field_prefix($this->slot) . 'sub4_answer', ''),
251
                $this->get_does_not_contain_submit_button_expectation(),
252
                $this->get_contains_try_again_button_expectation(true),
253
                $this->get_does_not_contain_correctness_expectation(),
254
                $this->get_contains_hint_expectation('This is the first hint.'));
255
        $this->check_output_contains_selectoptions(
256
                $this->get_contains_select_expectation('sub1_answer', $choices, 1, false),
257
                $this->get_contains_select_expectation('sub2_answer', $choices, 0, false),
258
                $this->get_contains_select_expectation('sub3_answer', $choices, 1, false),
259
                $this->get_contains_select_expectation('sub4_answer', $choices, 0, false));
260
 
261
        // Check that, if we review in this state, the try again button is disabled.
262
        $displayoptions = new question_display_options();
263
        $displayoptions->readonly = true;
264
        $html = $this->quba->render_question($this->slot, $displayoptions);
265
        $this->assert($this->get_contains_try_again_button_expectation(false), $html);
266
 
267
        // Try again.
268
        $this->process_submission(array('sub1_answer' => '',
269
                'sub2_answer' => '', 'sub3_answer' => '',
270
                'sub4_answer' => '', '-tryagain' => 1));
271
 
272
        // Verify.
273
        $this->check_current_state(question_state::$todo);
274
        $this->check_current_mark(null);
275
        $this->check_current_output(
276
                $this->get_contains_submit_button_expectation(true),
277
                $this->get_does_not_contain_feedback_expectation(),
278
                $this->get_tries_remaining_expectation(2),
279
                $this->get_no_hint_visible_expectation());
280
        $this->check_output_contains_selectoptions(
281
                $this->get_contains_select_expectation('sub1_answer', $choices, null, true),
282
                $this->get_contains_select_expectation('sub2_answer', $choices, null, true),
283
                $this->get_contains_select_expectation('sub3_answer', $choices, null, true),
284
                $this->get_contains_select_expectation('sub4_answer', $choices, null, true));
285
 
286
        // Submit a partially wrong response.
287
        $this->process_submission(array('sub1_answer' => '1', 'sub2_answer' => '1',
288
                'sub3_answer' => '1', 'sub4_answer' => '1', '-submit' => 1));
289
 
290
        // Verify.
291
        $this->check_current_state(question_state::$todo);
292
        $this->check_current_mark(null);
293
        $this->check_current_output(
294
                $this->get_contains_num_parts_correct(2),
295
                $this->get_contains_hidden_expectation(
296
                        $this->quba->get_field_prefix($this->slot) . 'sub1_answer', ''),
297
                $this->get_contains_hidden_expectation(
298
                        $this->quba->get_field_prefix($this->slot) . 'sub2_answer', '1'),
299
                $this->get_contains_hidden_expectation(
300
                        $this->quba->get_field_prefix($this->slot) . 'sub3_answer', ''),
301
                $this->get_contains_hidden_expectation(
302
                        $this->quba->get_field_prefix($this->slot) . 'sub4_answer', '1'),
303
                $this->get_does_not_contain_submit_button_expectation(),
304
                $this->get_contains_hint_expectation('This is the second hint.'));
305
        $this->check_output_contains_selectoptions(
306
                $this->get_contains_select_expectation('sub1_answer', $choices, 1, false),
307
                $this->get_contains_select_expectation('sub2_answer', $choices, 1, false),
308
                $this->get_contains_select_expectation('sub3_answer', $choices, 1, false),
309
                $this->get_contains_select_expectation('sub4_answer', $choices, 1, false));
310
 
311
        // Try again.
312
        $this->process_submission(array('sub1_answer' => '',
313
                'sub2_answer' => '1', 'sub3_answer' => '',
314
                'sub4_answer' => '1', '-tryagain' => 1));
315
 
316
        // Verify.
317
        $this->check_current_state(question_state::$todo);
318
        $this->check_current_mark(null);
319
        $this->check_current_output(
320
                $this->get_contains_submit_button_expectation(true),
321
                $this->get_does_not_contain_feedback_expectation(),
322
                $this->get_tries_remaining_expectation(1),
323
                $this->get_no_hint_visible_expectation());
324
        $this->check_output_contains_selectoptions(
325
                $this->get_contains_select_expectation('sub1_answer', $choices, '', true),
326
                $this->get_contains_select_expectation('sub2_answer', $choices, '1', true),
327
                $this->get_contains_select_expectation('sub3_answer', $choices, '', true),
328
                $this->get_contains_select_expectation('sub4_answer', $choices, '1', true));
329
    }
330
 
11 efrain 331
    public function test_interactive_partial_response_does_not_reveal_answer(): void {
1 efrain 332
 
333
        // Create a multianswer question.
334
        $q = \test_question_maker::make_question('multianswer', 'fourmc');
335
        $q->hints = array(
336
                new question_hint_with_parts(11, 'This is the first hint.', FORMAT_HTML, false, true),
337
                new question_hint_with_parts(12, 'This is the second hint.', FORMAT_HTML, true, true),
338
        );
339
        $choices = array('0' => 'California', '1' => 'Arizona');
340
 
341
        $this->start_attempt_at_question($q, 'interactive', 4);
342
 
343
        // Check the initial state.
344
        $this->check_current_state(question_state::$todo);
345
        $this->check_current_mark(null);
346
        $this->assertEquals('interactivecountback',
347
                $this->quba->get_question_attempt($this->slot)->get_behaviour_name());
348
        $this->check_current_output(
349
                $this->get_contains_marked_out_of_summary(),
350
                $this->get_contains_submit_button_expectation(true),
351
                $this->get_does_not_contain_validation_error_expectation(),
352
                $this->get_does_not_contain_feedback_expectation(),
353
                $this->get_tries_remaining_expectation(3),
354
                $this->get_does_not_contain_num_parts_correct(),
355
                $this->get_no_hint_visible_expectation());
356
        $this->check_output_contains_selectoptions(
357
                $this->get_contains_select_expectation('sub1_answer', $choices, null, true),
358
                $this->get_contains_select_expectation('sub2_answer', $choices, null, true),
359
                $this->get_contains_select_expectation('sub3_answer', $choices, null, true),
360
                $this->get_contains_select_expectation('sub4_answer', $choices, null, true));
361
 
362
        // Submit an incomplete response response.
363
        $this->process_submission(array('sub1_answer' => '1', 'sub2_answer' => '1', '-submit' => 1));
364
 
365
        // Verify.
366
        $this->check_current_state(question_state::$invalid);
367
        $this->check_current_mark(null);
368
        $this->check_current_output(
369
                $this->get_does_not_contain_num_parts_correct(),
370
                $this->get_contains_validation_error_expectation(),
371
                $this->get_contains_submit_button_expectation(true),
372
                $this->get_does_not_contain_try_again_button_expectation(),
373
                $this->get_does_not_contain_correctness_expectation(),
374
                $this->get_no_hint_visible_expectation());
375
        $this->check_output_contains_selectoptions(
376
                $this->get_contains_select_expectation('sub1_answer', $choices, 1, true),
377
                $this->get_contains_select_expectation('sub2_answer', $choices, 1, true),
378
                $this->get_contains_select_expectation('sub3_answer', $choices, null, true),
379
                $this->get_contains_select_expectation('sub4_answer', $choices, null, true));
380
        $this->render();
381
        $a = array('mark' => '0.00', 'max' => '1.00');
382
        $this->assertDoesNotMatchRegularExpression('~' . preg_quote(get_string('markoutofmax', 'question', $a), '~') . '~',
383
                $this->currentoutput);
384
        $a['mark'] = '1.00';
385
        $this->assertDoesNotMatchRegularExpression('~' . preg_quote(get_string('markoutofmax', 'question', $a), '~') . '~',
386
                $this->currentoutput);
387
    }
388
 
11 efrain 389
    public function test_interactivecountback_feedback(): void {
1 efrain 390
 
391
        // Create a multianswer question.
392
        $q = \test_question_maker::make_question('multianswer', 'fourmc');
393
        $q->hints = array(
394
            new question_hint_with_parts(11, 'This is the first hint.', FORMAT_HTML, true, true),
395
            new question_hint_with_parts(12, 'This is the second hint.', FORMAT_HTML, true, true),
396
        );
397
        $choices = array('0' => 'California', '1' => 'Arizona');
398
 
399
        $this->start_attempt_at_question($q, 'interactive', 12);
400
 
401
        // Check the initial state.
402
        $this->check_current_state(question_state::$todo);
403
        $this->check_current_mark(null);
404
        $this->assertEquals('interactivecountback',
405
                $this->quba->get_question_attempt($this->slot)->get_behaviour_name());
406
        $this->check_current_output(
407
                $this->get_contains_marked_out_of_summary(),
408
                $this->get_contains_submit_button_expectation(true),
409
                $this->get_does_not_contain_validation_error_expectation(),
410
                $this->get_does_not_contain_feedback_expectation(),
411
                $this->get_tries_remaining_expectation(3),
412
                $this->get_no_hint_visible_expectation());
413
        $this->check_output_contains_selectoptions(
414
                $this->get_contains_select_expectation('sub1_answer', $choices, null, true),
415
                $this->get_contains_select_expectation('sub2_answer', $choices, null, true),
416
                $this->get_contains_select_expectation('sub3_answer', $choices, null, true),
417
                $this->get_contains_select_expectation('sub4_answer', $choices, null, true));
418
 
419
        // Submit an answer with two right, and two wrong.
420
        $this->process_submission(array('sub1_answer' => '1', 'sub2_answer' => '1',
421
                'sub3_answer' => '1', 'sub4_answer' => '1', '-submit' => 1));
422
 
423
        // Verify.
424
        $this->check_current_state(question_state::$todo);
425
        $this->check_current_mark(null);
426
        $this->check_current_output(
427
                $this->get_does_not_contain_submit_button_expectation(),
428
                $this->get_contains_try_again_button_expectation(true),
429
                $this->get_does_not_contain_correctness_expectation(),
430
                new \question_pattern_expectation('/Tries remaining: 2/'),
431
                $this->get_contains_hint_expectation('This is the first hint.'));
432
        $this->check_output_contains_selectoptions(
433
                $this->get_contains_select_expectation('sub1_answer', $choices, 1, false),
434
                $this->get_contains_select_expectation('sub2_answer', $choices, 1, false),
435
                $this->get_contains_select_expectation('sub3_answer', $choices, 1, false),
436
                $this->get_contains_select_expectation('sub4_answer', $choices, 1, false));
437
 
438
        // Check that extract responses will return the reset data.
439
        $prefix = $this->quba->get_field_prefix($this->slot);
440
        $this->assertEquals(array('sub1_answer' => 1),
441
                $this->quba->extract_responses($this->slot, array($prefix . 'sub1_answer' => 1)));
442
 
443
        // Do try again.
444
        $this->process_submission(array('sub1_answer' => '',
445
                'sub2_answer' => '1', 'sub3_answer' => '',
446
                'sub4_answer' => '1', '-tryagain' => 1));
447
 
448
        // Verify.
449
        $this->check_current_state(question_state::$todo);
450
        $this->check_current_mark(null);
451
        $this->check_current_output(
452
                $this->get_contains_submit_button_expectation(true),
453
                $this->get_does_not_contain_feedback_expectation(),
454
                $this->get_tries_remaining_expectation(2),
455
                $this->get_no_hint_visible_expectation());
456
        $this->check_output_contains_selectoptions(
457
                $this->get_contains_select_expectation('sub1_answer', $choices, '', true),
458
                $this->get_contains_select_expectation('sub2_answer', $choices, '1', true),
459
                $this->get_contains_select_expectation('sub3_answer', $choices, '', true),
460
                $this->get_contains_select_expectation('sub4_answer', $choices, '1', true));
461
 
462
        // Submit the right answer.
463
        $this->process_submission(array('sub1_answer' => '0', 'sub2_answer' => '1',
464
                'sub3_answer' => '0', 'sub4_answer' => '1', '-submit' => 1));
465
 
466
        // Verify.
467
        $this->check_current_state(question_state::$gradedright);
468
        $this->check_current_mark(10);
469
        $this->check_current_output(
470
                $this->get_does_not_contain_submit_button_expectation(),
471
                $this->get_does_not_contain_try_again_button_expectation(),
472
                $this->get_contains_correct_expectation(),
473
                new \question_no_pattern_expectation('/class="control\b[^"]*\bpartiallycorrect"/'));
474
        $this->check_output_contains_selectoptions(
475
                $this->get_contains_select_expectation('sub1_answer', $choices, '0', false),
476
                $this->get_contains_select_expectation('sub2_answer', $choices, '1', false),
477
                $this->get_contains_select_expectation('sub3_answer', $choices, '0', false),
478
                $this->get_contains_select_expectation('sub4_answer', $choices, '1', false));
479
    }
480
 
11 efrain 481
    public function test_deferred_feedback_multiple(): void {
1 efrain 482
 
483
        // Create a multianswer question.
484
        $q = \test_question_maker::make_question('multianswer', 'multiple');
485
        $this->start_attempt_at_question($q, 'deferredfeedback', 2);
486
 
487
        // Check the initial state.
488
        $this->check_current_state(question_state::$todo);
489
        $this->check_current_mark(null);
490
        $this->check_current_output(
491
            $this->get_contains_marked_out_of_summary(),
492
            $this->get_does_not_contain_feedback_expectation(),
493
            $this->get_does_not_contain_validation_error_expectation());
494
 
495
        // Save in incomplete answer.
496
        $this->process_submission(array('sub1_choice0' => '1', 'sub1_choice1' => '1',
497
                                        'sub1_choice2' => '', 'sub1_choice3' => '',
498
                                        'sub1_choice4' => '', 'sub1_choice5' => '1',
499
                                        ));
500
 
501
        // Verify.
502
        $this->check_current_state(question_state::$invalid);
503
        $this->check_current_mark(null);
504
        $this->check_current_output(
505
            $this->get_contains_marked_out_of_summary(),
506
            $this->get_does_not_contain_feedback_expectation(),
507
            $this->get_contains_validation_error_expectation());
508
 
509
        // Save a partially correct answer.
510
        $this->process_submission(array('sub1_choice0' => '1', 'sub1_choice1' => '',
511
                                        'sub1_choice2' => '', 'sub1_choice3' => '',
512
                                        'sub1_choice4' => '1', 'sub1_choice5' => '1',
513
                                        'sub2_choice0' => '', 'sub2_choice1' => '',
514
                                        'sub2_choice2' => '', 'sub2_choice3' => '',
515
                                        'sub2_choice4' => '1',
516
                                  ));
517
 
518
        // Verify.
519
        $this->check_current_state(question_state::$complete);
520
        $this->check_current_mark(null);
521
        $this->check_current_output(
522
            $this->get_contains_marked_out_of_summary(),
523
            $this->get_does_not_contain_feedback_expectation(),
524
            $this->get_does_not_contain_validation_error_expectation());
525
 
526
        // Now submit all and finish.
527
        $this->finish();
528
 
529
        // Verify.
530
        $this->check_current_state(question_state::$gradedpartial);
531
        $this->check_current_mark(1.5);
532
        $this->check_current_output(
533
            $this->get_contains_mark_summary(1.5),
534
            $this->get_contains_partcorrect_expectation(),
535
            $this->get_does_not_contain_validation_error_expectation());
536
    }
537
 
538
    /**
539
     * Test corrupted question display.
540
     *
541
     * @covers \qtype_multianswer_renderer::subquestion
542
     */
11 efrain 543
    public function test_corrupted_question(): void {
1 efrain 544
        global $DB;
545
 
546
        $syscontext = \context_system::instance();
547
        $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
548
        $category = $generator->create_question_category(['contextid' => $syscontext->id]);
549
 
550
        $fromform = test_question_maker::get_question_form_data('multianswer', 'twosubq');
551
        $fromform->category = $category->id . ',' . $syscontext->id;
552
 
553
        $question = new \stdClass();
554
        $question->category = $category->id;
555
        $question->qtype = 'multianswer';
556
        $question->createdby = 0;
557
 
558
        $question = (new qtype_multianswer)->save_question($question, $fromform);
559
        $questiondata = question_bank::load_question_data($question->id);
560
        $questiontodeletekey = array_keys($questiondata->options->questions)[0];
561
        $questiontodelete = $questiondata->options->questions[$questiontodeletekey];
562
        $DB->delete_records('question', ['id' => $questiontodelete->id]);
563
 
564
        question_bank::notify_question_edited($question->id);
565
        $question = question_bank::load_question($question->id);
566
 
567
        $this->start_attempt_at_question($question, 'deferredfeedback', 2);
568
        $this->check_current_output(
569
            $this->get_contains_marked_out_of_summary(),
570
            $this->get_does_not_contain_feedback_expectation(),
571
            $this->get_does_not_contain_validation_error_expectation(),
572
            $this->get_contains_corruption_notification(),
573
            $this->get_contains_corrupted_subquestion_message(),
574
        );
575
    }
576
}