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_match;
18
 
19
use question_hint_with_parts;
20
use question_state;
21
 
22
defined('MOODLE_INTERNAL') || die();
23
 
24
global $CFG;
25
require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
26
 
27
 
28
/**
29
 * Unit tests for the matching question type.
30
 *
31
 * @package   qtype_match
32
 * @copyright 2010 The Open University
33
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34
 */
1441 ariadna 35
final class walkthrough_test extends \qbehaviour_walkthrough_test_base {
1 efrain 36
 
11 efrain 37
    public function test_deferred_feedback_unanswered(): void {
1 efrain 38
 
39
        // Create a matching question.
40
        $m = \test_question_maker::make_question('match');
41
        $m->shufflestems = false;
42
        $this->start_attempt_at_question($m, 'deferredfeedback', 4);
43
 
44
        $choiceorder = $m->get_choice_order();
45
        $orderforchoice = array_combine(array_values($choiceorder), array_keys($choiceorder));
46
        $choices = array(0 => get_string('choose') . '...');
47
        foreach ($choiceorder as $key => $choice) {
48
            $choices[$key] = $m->choices[$choice];
49
        }
50
 
51
        // Check the initial state.
52
        $this->check_current_state(question_state::$todo);
53
        $this->check_current_mark(null);
54
        $this->check_current_output(
55
                $this->get_contains_question_text_expectation($m),
56
                $this->get_does_not_contain_feedback_expectation());
57
        $this->check_output_contains_selectoptions(
58
                $this->get_contains_select_expectation('sub0', $choices, null, true),
59
                $this->get_contains_select_expectation('sub1', $choices, null, true),
60
                $this->get_contains_select_expectation('sub2', $choices, null, true),
61
                $this->get_contains_select_expectation('sub3', $choices, null, true));
62
        $this->check_step_count(1);
63
 
64
        // Save a blank response.
65
        $this->process_submission(array('sub0' => '0', 'sub1' => '0',
66
                'sub2' => '0', 'sub3' => '0'));
67
 
68
        // Verify.
69
        $this->check_current_state(question_state::$todo);
70
        $this->check_current_mark(null);
71
        $this->check_current_output(
72
                $this->get_contains_question_text_expectation($m),
73
                $this->get_does_not_contain_feedback_expectation());
74
        $this->check_output_contains_selectoptions(
75
                $this->get_contains_select_expectation('sub0', $choices, null, true),
76
                $this->get_contains_select_expectation('sub1', $choices, null, true),
77
                $this->get_contains_select_expectation('sub2', $choices, null, true),
78
                $this->get_contains_select_expectation('sub3', $choices, null, true));
79
        $this->check_step_count(1);
80
 
81
        // Finish the attempt.
82
        $this->quba->finish_all_questions();
83
 
84
        // Verify.
85
        $this->check_current_state(question_state::$gaveup);
86
        $this->check_current_mark(null);
87
        $this->check_output_contains_selectoptions(
88
                $this->get_contains_select_expectation('sub0', $choices, null, false),
89
                $this->get_contains_select_expectation('sub1', $choices, null, false),
90
                $this->get_contains_select_expectation('sub2', $choices, null, false),
91
                $this->get_contains_select_expectation('sub3', $choices, null, false));
92
    }
93
 
11 efrain 94
    public function test_deferred_feedback_partial_answer(): void {
1 efrain 95
 
96
        // Create a matching question.
97
        $m = \test_question_maker::make_question('match');
98
        $m->shufflestems = false;
99
        $this->start_attempt_at_question($m, 'deferredfeedback', 4);
100
 
101
        $choiceorder = $m->get_choice_order();
102
        $orderforchoice = array_combine(array_values($choiceorder), array_keys($choiceorder));
103
        $choices = array(0 => get_string('choose') . '...');
104
        foreach ($choiceorder as $key => $choice) {
105
            $choices[$key] = $m->choices[$choice];
106
        }
107
 
108
        // Check the initial state.
109
        $this->check_current_state(question_state::$todo);
110
        $this->check_current_mark(null);
111
        $this->check_current_output(
112
                $this->get_contains_question_text_expectation($m),
113
                $this->get_does_not_contain_feedback_expectation());
114
        $this->check_output_contains_selectoptions(
115
                $this->get_contains_select_expectation('sub0', $choices, null, true),
116
                $this->get_contains_select_expectation('sub1', $choices, null, true),
117
                $this->get_contains_select_expectation('sub2', $choices, null, true),
118
                $this->get_contains_select_expectation('sub3', $choices, null, true));
119
 
120
        // Save a partial response.
121
        $this->process_submission(array('sub0' => $orderforchoice[1],
122
                'sub1' => $orderforchoice[2], 'sub2' => '0', 'sub3' => '0'));
123
 
124
        // Verify.
125
        $this->check_current_state(question_state::$invalid);
126
        $this->check_current_mark(null);
127
        $this->check_current_output(
128
                $this->get_contains_question_text_expectation($m),
129
                $this->get_does_not_contain_feedback_expectation());
130
        $this->check_output_contains_selectoptions(
131
                $this->get_contains_select_expectation('sub0', $choices, $orderforchoice[1], true),
132
                $this->get_contains_select_expectation('sub1', $choices, $orderforchoice[2], true),
133
                $this->get_contains_select_expectation('sub2', $choices, null, true),
134
                $this->get_contains_select_expectation('sub3', $choices, null, true));
135
 
136
        // Finish the attempt.
137
        $this->quba->finish_all_questions();
138
 
139
        // Verify.
140
        $this->check_current_state(question_state::$gradedpartial);
141
        $this->check_current_mark(2);
142
        $this->check_current_output(
143
                $this->get_contains_partcorrect_expectation());
144
        $this->check_output_contains_selectoptions(
145
                $this->get_contains_select_expectation('sub0', $choices, $orderforchoice[1], false),
146
                $this->get_contains_select_expectation('sub1', $choices, $orderforchoice[2], false),
147
                $this->get_contains_select_expectation('sub2', $choices, null, false),
148
                $this->get_contains_select_expectation('sub3', $choices, null, false));
149
    }
150
 
11 efrain 151
    public function test_interactive_correct_no_submit(): void {
1 efrain 152
 
153
        // Create a matching question.
154
        $m = \test_question_maker::make_question('match');
155
        $m->hints = array(
156
            new question_hint_with_parts(11, 'This is the first hint.', FORMAT_HTML, false, false),
157
            new question_hint_with_parts(12, 'This is the second hint.', FORMAT_HTML, true, true),
158
        );
159
        $m->shufflestems = false;
160
        $this->start_attempt_at_question($m, 'interactive', 4);
161
 
162
        $choiceorder = $m->get_choice_order();
163
        $orderforchoice = array_combine(array_values($choiceorder), array_keys($choiceorder));
164
        $choices = array(0 => get_string('choose') . '...');
165
        foreach ($choiceorder as $key => $choice) {
166
            $choices[$key] = $m->choices[$choice];
167
        }
168
 
169
        // Check the initial state.
170
        $this->check_current_state(question_state::$todo);
171
        $this->check_current_mark(null);
172
        $this->check_current_output(
173
                $this->get_contains_submit_button_expectation(true),
174
                $this->get_does_not_contain_feedback_expectation(),
175
                $this->get_tries_remaining_expectation(3),
176
                $this->get_no_hint_visible_expectation());
177
        $this->check_output_contains_selectoptions(
178
                $this->get_contains_select_expectation('sub0', $choices, null, true),
179
                $this->get_contains_select_expectation('sub1', $choices, null, true),
180
                $this->get_contains_select_expectation('sub2', $choices, null, true),
181
                $this->get_contains_select_expectation('sub3', $choices, null, true));
182
 
183
        // Save the right answer.
184
        $this->process_submission(array('sub0' => $orderforchoice[1],
185
                'sub1' => $orderforchoice[2], 'sub2' => $orderforchoice[2],
186
                'sub3' => $orderforchoice[1]));
187
 
188
        // Finish the attempt without clicking check.
189
        $this->quba->finish_all_questions();
190
 
191
        // Verify.
192
        $this->check_current_state(question_state::$gradedright);
193
        $this->check_current_mark(4);
194
        $this->check_current_output(
195
                $this->get_does_not_contain_submit_button_expectation(),
196
                $this->get_contains_correct_expectation(),
197
                $this->get_no_hint_visible_expectation());
198
        $this->check_output_contains_selectoptions(
199
                $this->get_contains_select_expectation('sub0', $choices, $orderforchoice[1], false),
200
                $this->get_contains_select_expectation('sub1', $choices, $orderforchoice[2], false),
201
                $this->get_contains_select_expectation('sub2', $choices, $orderforchoice[2], false),
202
                $this->get_contains_select_expectation('sub3', $choices, $orderforchoice[1], false));
203
 
204
        // Regrade with a new version of the question.
205
        /** @var \qtype_match_question $oldm */
206
        $oldm = \test_question_maker::make_question('match');
207
        $oldm->stems = [11 => 'Dog', 12 => 'Frog', 13 => 'Toad', 14 => 'Cat'];
208
        $oldm->stemformat = [11 => FORMAT_HTML, 12 => FORMAT_HTML, 13 => FORMAT_HTML, 14 => FORMAT_HTML];
209
        $oldm->choices = [11 => 'Mammal', 12 => 'Amphibian', 13 => 'Insect'];
210
        $oldm->right = [11 => 11, 12 => 12, 13 => 12, 14 => 11];
211
        $this->quba->regrade_question($this->slot, true, null, $oldm);
212
 
213
        // Verify.
214
        $this->check_current_mark(4);
215
        $this->render();
216
        $this->assertStringContainsString('Cat', $this->currentoutput);
217
        $this->assertStringContainsString('Insect', $this->currentoutput);
218
        $this->assertStringNotContainsString(
219
                get_string('deletedsubquestion', 'qtype_match'), $this->currentoutput);
220
        $this->assertStringNotContainsString(
221
                get_string('deletedchoice', 'qtype_match'), $this->currentoutput);
222
    }
223
 
11 efrain 224
    public function test_interactive_partial_no_submit(): void {
1 efrain 225
 
226
        // Create a matching question.
227
        $m = \test_question_maker::make_question('match');
228
        $m->hints = array(
229
            new question_hint_with_parts(11, 'This is the first hint.', FORMAT_HTML, false, false),
230
            new question_hint_with_parts(12, 'This is the second hint.', FORMAT_HTML, true, true),
231
        );
232
        $m->shufflestems = false;
233
        $this->start_attempt_at_question($m, 'interactive', 4);
234
 
235
        $choiceorder = $m->get_choice_order();
236
        $orderforchoice = array_combine(array_values($choiceorder), array_keys($choiceorder));
237
        $choices = array(0 => get_string('choose') . '...');
238
        foreach ($choiceorder as $key => $choice) {
239
            $choices[$key] = $m->choices[$choice];
240
        }
241
 
242
        // Check the initial state.
243
        $this->check_current_state(question_state::$todo);
244
        $this->check_current_mark(null);
245
        $this->check_current_output(
246
                $this->get_contains_submit_button_expectation(true),
247
                $this->get_does_not_contain_feedback_expectation(),
248
                $this->get_tries_remaining_expectation(3),
249
                $this->get_no_hint_visible_expectation());
250
        $this->check_output_contains_selectoptions(
251
                $this->get_contains_select_expectation('sub0', $choices, null, true),
252
                $this->get_contains_select_expectation('sub1', $choices, null, true),
253
                $this->get_contains_select_expectation('sub2', $choices, null, true),
254
                $this->get_contains_select_expectation('sub3', $choices, null, true));
255
 
256
        // Save the right answer.
257
        $this->process_submission(array('sub0' => $orderforchoice[1],
258
                'sub1' => $orderforchoice[2], 'sub2' => $orderforchoice[1],
259
                'sub3' => '0'));
260
 
261
        // Finish the attempt without clicking check.
262
        $this->quba->finish_all_questions();
263
 
264
        // Verify.
265
        $this->check_current_state(question_state::$gradedpartial);
266
        $this->check_current_mark(2);
267
        $this->check_current_output(
268
                $this->get_does_not_contain_submit_button_expectation(),
269
                $this->get_contains_partcorrect_expectation(),
270
                $this->get_no_hint_visible_expectation());
271
        $this->check_output_contains_selectoptions(
272
                $this->get_contains_select_expectation('sub0', $choices, $orderforchoice[1], false),
273
                $this->get_contains_select_expectation('sub1', $choices, $orderforchoice[2], false),
274
                $this->get_contains_select_expectation('sub2', $choices, $orderforchoice[1], false),
275
                $this->get_contains_select_expectation('sub3', $choices, null, false));
276
    }
277
 
11 efrain 278
    public function test_interactive_with_invalid(): void {
1 efrain 279
 
280
        // Create a matching question.
281
        $m = \test_question_maker::make_question('match');
282
        $m->hints = array(
283
            new question_hint_with_parts(11, 'This is the first hint.', FORMAT_HTML, false, false),
284
            new question_hint_with_parts(12, 'This is the second hint.', FORMAT_HTML, true, true),
285
        );
286
        $m->shufflestems = false;
287
        $this->start_attempt_at_question($m, 'interactive', 4);
288
 
289
        $choiceorder = $m->get_choice_order();
290
        $orderforchoice = array_combine(array_values($choiceorder), array_keys($choiceorder));
291
        $choices = array(0 => get_string('choose') . '...');
292
        foreach ($choiceorder as $key => $choice) {
293
            $choices[$key] = $m->choices[$choice];
294
        }
295
 
296
        // Check the initial state.
297
        $this->check_current_state(question_state::$todo);
298
        $this->check_current_mark(null);
299
        $this->check_current_output(
300
                $this->get_contains_submit_button_expectation(true),
301
                $this->get_does_not_contain_feedback_expectation(),
302
                $this->get_tries_remaining_expectation(3),
303
                $this->get_no_hint_visible_expectation());
304
        $this->check_output_contains_selectoptions(
305
                $this->get_contains_select_expectation('sub0', $choices, null, true),
306
                $this->get_contains_select_expectation('sub1', $choices, null, true),
307
                $this->get_contains_select_expectation('sub2', $choices, null, true),
308
                $this->get_contains_select_expectation('sub3', $choices, null, true));
309
 
310
        // Try to submit an invalid answer.
311
        $this->process_submission(array('sub0' => '0',
312
                'sub1' => '0', 'sub2' => '0',
313
                'sub3' => '0', '-submit' => '1'));
314
 
315
        // Verify.
316
        $this->check_current_state(question_state::$invalid);
317
        $this->check_current_mark(null);
318
        $this->check_current_output(
319
                $this->get_contains_submit_button_expectation(true),
320
                $this->get_does_not_contain_feedback_expectation(),
321
                $this->get_invalid_answer_expectation(),
322
                $this->get_no_hint_visible_expectation());
323
        $this->check_output_contains_selectoptions(
324
                $this->get_contains_select_expectation('sub0', $choices, null, true),
325
                $this->get_contains_select_expectation('sub1', $choices, null, true),
326
                $this->get_contains_select_expectation('sub2', $choices, null, true),
327
                $this->get_contains_select_expectation('sub3', $choices, null, true));
328
 
329
        // Now submit the right answer.
330
        $this->process_submission(array('sub0' => $orderforchoice[1],
331
                'sub1' => $orderforchoice[2], 'sub2' => $orderforchoice[2],
332
                'sub3' => $orderforchoice[1], '-submit' => '1'));
333
 
334
        // Verify.
335
        $this->check_current_state(question_state::$gradedright);
336
        $this->check_current_mark(4);
337
        $this->check_current_output(
338
                $this->get_does_not_contain_submit_button_expectation(),
339
                $this->get_contains_correct_expectation(),
340
                $this->get_no_hint_visible_expectation());
341
        $this->check_output_contains_selectoptions(
342
                $this->get_contains_select_expectation('sub0', $choices, $orderforchoice[1], false),
343
                $this->get_contains_select_expectation('sub1', $choices, $orderforchoice[2], false),
344
                $this->get_contains_select_expectation('sub2', $choices, $orderforchoice[2], false),
345
                $this->get_contains_select_expectation('sub3', $choices, $orderforchoice[1], false));
346
    }
347
 
11 efrain 348
    public function test_match_with_tricky_html_choices(): void {
1 efrain 349
 
350
        // Create a matching question.
351
        $m = \test_question_maker::make_question('match');
352
        $m->stems = array(
353
            1 => '(1, 2]',
354
            2 => '[1, 2]',
355
            3 => '[1, 2)',
356
        );
357
        $m->choices = array(
358
            1 => '1 < x ≤ 2',
359
            2 => '1 ≤ x ≤ 2',
360
            3 => '1 ≤ x < 2',
361
        );
362
        $m->right = array(1 => 1, 2 => 2, 3 => 3);
363
        $m->shufflestems = false;
364
        $this->start_attempt_at_question($m, 'deferredfeedback', 3);
365
 
366
        $choiceorder = $m->get_choice_order();
367
        $orderforchoice = array_combine(array_values($choiceorder), array_keys($choiceorder));
368
        $choices = array(0 => get_string('choose') . '...');
369
        foreach ($choiceorder as $key => $choice) {
370
            $choices[$key] = $m->choices[$choice];
371
        }
372
 
373
        // Check the initial state.
374
        $this->check_current_state(question_state::$todo);
375
        $this->check_current_mark(null);
376
        // Do not use check_output_contains_selectoptions as there are multibyte characters ('1 ≤ x ≤ 2') that
377
        // seem to be read as ascii ('1 ≤ x ≤ 2') in this test.
378
        $this->check_current_output(
379
                $this->get_contains_select_expectation('sub0', $choices, null, true),
380
                $this->get_contains_select_expectation('sub1', $choices, null, true),
381
                $this->get_contains_select_expectation('sub2', $choices, null, true),
382
                $this->get_contains_question_text_expectation($m),
383
                $this->get_does_not_contain_feedback_expectation());
384
        $this->check_step_count(1);
385
 
386
        $rightresponse = array('sub0' => $orderforchoice[1],
387
                'sub1' => $orderforchoice[2], 'sub2' => $orderforchoice[3]);
388
        $rightresponsesummary =
389
                '(1, 2] -> 1 < x ≤ 2; [1, 2] -> 1 ≤ x ≤ 2; [1, 2) -> 1 ≤ x < 2';
390
 
391
        $this->process_submission($rightresponse);
392
        $this->finish();
393
 
394
        $this->assertEquals($rightresponsesummary, $m->summarise_response($rightresponse));
395
 
396
        $this->displayoptions->history = 1;
397
        $this->check_current_output(
398
                new \question_pattern_expectation('/' .
399
                        preg_quote(htmlspecialchars($rightresponsesummary, ENT_COMPAT), '/') . '/'));
400
    }
401
 
11 efrain 402
    public function test_match_clear_wrong(): void {
1 efrain 403
 
404
        // Create a matching question.
405
        $m = \test_question_maker::make_question('match');
406
        $m->hints = array(
407
            new question_hint_with_parts(11, 'This is the first hint.', FORMAT_HTML, false, true),
408
            new question_hint_with_parts(12, 'This is the second hint.', FORMAT_HTML, true, true),
409
        );
410
        $m->shufflestems = false;
411
        $this->start_attempt_at_question($m, 'interactive', 4);
412
 
413
        $choiceorder = $m->get_choice_order();
414
        $orderforchoice = array_combine(array_values($choiceorder), array_keys($choiceorder));
415
        $choices = array(0 => get_string('choose') . '...');
416
        foreach ($choiceorder as $key => $choice) {
417
            $choices[$key] = $m->choices[$choice];
418
        }
419
 
420
        // Check the initial state.
421
        $this->check_current_state(question_state::$todo);
422
        $this->check_current_mark(null);
423
        $this->check_current_output(
424
                $this->get_contains_submit_button_expectation(true),
425
                $this->get_does_not_contain_feedback_expectation(),
426
                $this->get_tries_remaining_expectation(3),
427
                $this->get_no_hint_visible_expectation());
428
        $this->check_output_contains_selectoptions(
429
                $this->get_contains_select_expectation('sub0', $choices, null, true),
430
                $this->get_contains_select_expectation('sub1', $choices, null, true),
431
                $this->get_contains_select_expectation('sub2', $choices, null, true),
432
                $this->get_contains_select_expectation('sub3', $choices, null, true));
433
 
434
        // Submit a completely wrong response.
435
        $this->process_submission(array('sub0' => $orderforchoice[3],
436
                'sub1' => $orderforchoice[3], 'sub2' => $orderforchoice[3],
437
                'sub3' => $orderforchoice[3], '-submit' => 1));
438
 
439
        // Verify.
440
        $this->check_current_state(question_state::$todo);
441
        $this->check_current_mark(null);
442
        $this->check_current_output(
443
                $this->get_contains_hidden_expectation(
444
                        $this->quba->get_field_prefix($this->slot) . 'sub0', '0'),
445
                $this->get_contains_hidden_expectation(
446
                        $this->quba->get_field_prefix($this->slot) . 'sub1', '0'),
447
                $this->get_contains_hidden_expectation(
448
                        $this->quba->get_field_prefix($this->slot) . 'sub2', '0'),
449
                $this->get_contains_hidden_expectation(
450
                        $this->quba->get_field_prefix($this->slot) . 'sub3', '0'),
451
                $this->get_does_not_contain_submit_button_expectation(),
452
                $this->get_contains_hint_expectation('This is the first hint.'));
453
        $this->check_output_contains_selectoptions(
454
                $this->get_contains_select_expectation('sub0', $choices, $orderforchoice[3], false),
455
                $this->get_contains_select_expectation('sub1', $choices, $orderforchoice[3], false),
456
                $this->get_contains_select_expectation('sub2', $choices, $orderforchoice[3], false),
457
                $this->get_contains_select_expectation('sub3', $choices, $orderforchoice[3], false));
458
 
459
        // Try again.
460
        $this->process_submission(array('sub0' => 0,
461
                'sub1' => 0, 'sub2' => 0,
462
                'sub3' => 0, '-tryagain' => 1));
463
 
464
        // Verify.
465
        $this->check_current_state(question_state::$todo);
466
        $this->check_current_mark(null);
467
        $this->check_current_output(
468
                $this->get_contains_submit_button_expectation(true),
469
                $this->get_does_not_contain_feedback_expectation(),
470
                $this->get_tries_remaining_expectation(2),
471
                $this->get_no_hint_visible_expectation());
472
        $this->check_output_contains_selectoptions(
473
                $this->get_contains_select_expectation('sub0', $choices, null, true),
474
                $this->get_contains_select_expectation('sub1', $choices, null, true),
475
                $this->get_contains_select_expectation('sub2', $choices, null, true),
476
                $this->get_contains_select_expectation('sub3', $choices, null, true));
477
 
478
        // Submit a partially wrong response.
479
        $this->process_submission(array('sub0' => $orderforchoice[3],
480
                'sub1' => $orderforchoice[3], 'sub2' => $orderforchoice[2],
481
                'sub3' => $orderforchoice[1], '-submit' => 1));
482
 
483
        // Verify.
484
        $this->check_current_state(question_state::$todo);
485
        $this->check_current_mark(null);
486
        $this->check_current_output(
487
                $this->get_contains_hidden_expectation(
488
                        $this->quba->get_field_prefix($this->slot) . 'sub0', '0'),
489
                $this->get_contains_hidden_expectation(
490
                        $this->quba->get_field_prefix($this->slot) . 'sub1', '0'),
491
                $this->get_contains_hidden_expectation(
492
                        $this->quba->get_field_prefix($this->slot) . 'sub2', $orderforchoice[2]),
493
                $this->get_contains_hidden_expectation(
494
                        $this->quba->get_field_prefix($this->slot) . 'sub3', $orderforchoice[1]),
495
                $this->get_does_not_contain_submit_button_expectation(),
496
                $this->get_contains_hint_expectation('This is the second hint.'));
497
        $this->check_output_contains_selectoptions(
498
                $this->get_contains_select_expectation('sub0', $choices, $orderforchoice[3], false),
499
                $this->get_contains_select_expectation('sub1', $choices, $orderforchoice[3], false),
500
                $this->get_contains_select_expectation('sub2', $choices, $orderforchoice[2], false),
501
                $this->get_contains_select_expectation('sub3', $choices, $orderforchoice[1], false));
502
 
503
        // Try again.
504
        $this->process_submission(array('sub0' => 0,
505
                'sub1' => 0, 'sub2' => $orderforchoice[2],
506
                'sub3' => $orderforchoice[1], '-tryagain' => 1));
507
 
508
        // Verify.
509
        $this->check_current_state(question_state::$todo);
510
        $this->check_current_mark(null);
511
        $this->check_current_output(
512
                $this->get_contains_submit_button_expectation(true),
513
                $this->get_does_not_contain_feedback_expectation(),
514
                $this->get_tries_remaining_expectation(1),
515
                $this->get_no_hint_visible_expectation());
516
        $this->check_output_contains_selectoptions(
517
                $this->get_contains_select_expectation('sub0', $choices, null, true),
518
                $this->get_contains_select_expectation('sub1', $choices, null, true),
519
                $this->get_contains_select_expectation('sub2', $choices, $orderforchoice[2], true),
520
                $this->get_contains_select_expectation('sub3', $choices, $orderforchoice[1], true));
521
 
522
    }
523
}