MDL-70153 qtype_essay: Add behat test for attachments max size
[moodle.git] / question / engine / tests / datalib_test.php
CommitLineData
cf256c05
TH
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Unit tests for parts of {@link question_engine_data_mapper}.
19 *
20 * @package core_question
21 * @category test
22 * @copyright 2014 The Open University
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26
27defined('MOODLE_INTERNAL') || die();
28
29global $CFG;
1fcf0ca8
RS
30require_once(__DIR__ . '/../lib.php');
31require_once(__DIR__ . '/helpers.php');
cf256c05
TH
32
33
34/**
35 * Unit tests for parts of {@link question_engine_data_mapper}.
36 *
37 * Note that many of the methods used when attempting questions, like
38 * load_questions_usage_by_activity, insert_question_*, delete_steps are
39 * tested elsewhere, e.g. by {@link question_usage_autosave_test}. We do not
40 * re-test them here.
41 *
42 * @copyright 2014 The Open University
43 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44 */
45class question_engine_data_mapper_testcase extends qbehaviour_walkthrough_test_base {
46
47 /**
48 * We create two usages, each with two questions, a short-answer marked
49 * out of 5, and and essay marked out of 10. We just start these attempts.
50 *
51 * Then we change the max mark for the short-answer question in one of the
52 * usages to 20, using a qubaid_list, and verify.
53 *
54 * Then we change the max mark for the essay question in the other
55 * usage to 2, using a qubaid_join, and verify.
56 */
57 public function test_set_max_mark_in_attempts() {
58
59 // Set up some things the tests will need.
60 $this->resetAfterTest();
61 $dm = new question_engine_data_mapper();
62
63 // Create the questions.
64 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
65 $cat = $generator->create_question_category();
66 $sa = $generator->create_question('shortanswer', null,
67 array('category' => $cat->id));
68 $essay = $generator->create_question('essay', null,
69 array('category' => $cat->id));
70
71 // Create the first usage.
72 $q = question_bank::load_question($sa->id);
73 $this->start_attempt_at_question($q, 'interactive', 5);
74
75 $q = question_bank::load_question($essay->id);
76 $this->start_attempt_at_question($q, 'interactive', 10);
77
78 $this->finish();
79 $this->save_quba();
80 $usage1id = $this->quba->get_id();
81
82 // Create the second usage.
83 $this->quba = question_engine::make_questions_usage_by_activity('unit_test',
84 context_system::instance());
85
86 $q = question_bank::load_question($sa->id);
87 $this->start_attempt_at_question($q, 'interactive', 5);
88 $this->process_submission(array('answer' => 'fish'));
89
90 $q = question_bank::load_question($essay->id);
91 $this->start_attempt_at_question($q, 'interactive', 10);
92
93 $this->finish();
94 $this->save_quba();
95 $usage2id = $this->quba->get_id();
96
97 // Test set_max_mark_in_attempts with a qubaid_list.
98 $usagestoupdate = new qubaid_list(array($usage1id));
99 $dm->set_max_mark_in_attempts($usagestoupdate, 1, 20.0);
100 $quba1 = question_engine::load_questions_usage_by_activity($usage1id);
101 $quba2 = question_engine::load_questions_usage_by_activity($usage2id);
102 $this->assertEquals(20, $quba1->get_question_max_mark(1));
103 $this->assertEquals(10, $quba1->get_question_max_mark(2));
104 $this->assertEquals( 5, $quba2->get_question_max_mark(1));
105 $this->assertEquals(10, $quba2->get_question_max_mark(2));
106
107 // Test set_max_mark_in_attempts with a qubaid_join.
108 $usagestoupdate = new qubaid_join('{question_usages} qu', 'qu.id',
109 'qu.id = :usageid', array('usageid' => $usage2id));
110 $dm->set_max_mark_in_attempts($usagestoupdate, 2, 2.0);
111 $quba1 = question_engine::load_questions_usage_by_activity($usage1id);
112 $quba2 = question_engine::load_questions_usage_by_activity($usage2id);
113 $this->assertEquals(20, $quba1->get_question_max_mark(1));
114 $this->assertEquals(10, $quba1->get_question_max_mark(2));
115 $this->assertEquals( 5, $quba2->get_question_max_mark(1));
116 $this->assertEquals( 2, $quba2->get_question_max_mark(2));
117
118 // Test the nothing to do case.
119 $usagestoupdate = new qubaid_join('{question_usages} qu', 'qu.id',
120 'qu.id = :usageid', array('usageid' => -1));
121 $dm->set_max_mark_in_attempts($usagestoupdate, 2, 2.0);
122 $quba1 = question_engine::load_questions_usage_by_activity($usage1id);
123 $quba2 = question_engine::load_questions_usage_by_activity($usage2id);
124 $this->assertEquals(20, $quba1->get_question_max_mark(1));
125 $this->assertEquals(10, $quba1->get_question_max_mark(2));
126 $this->assertEquals( 5, $quba2->get_question_max_mark(1));
127 $this->assertEquals( 2, $quba2->get_question_max_mark(2));
128 }
bb93fc24
TH
129
130 public function test_load_used_variants() {
131 $this->resetAfterTest();
132 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
133
134 $cat = $generator->create_question_category();
135 $questiondata1 = $generator->create_question('shortanswer', null, array('category' => $cat->id));
136 $questiondata2 = $generator->create_question('shortanswer', null, array('category' => $cat->id));
137 $questiondata3 = $generator->create_question('shortanswer', null, array('category' => $cat->id));
138
139 $quba = question_engine::make_questions_usage_by_activity('test', context_system::instance());
140 $quba->set_preferred_behaviour('deferredfeedback');
141 $question1 = question_bank::load_question($questiondata1->id);
142 $question3 = question_bank::load_question($questiondata3->id);
143 $quba->add_question($question1);
144 $quba->add_question($question1);
145 $quba->add_question($question3);
146 $quba->start_all_questions();
147 question_engine::save_questions_usage_by_activity($quba);
148
149 $this->assertEquals(array(
150 $questiondata1->id => array(1 => 2),
151 $questiondata2->id => array(),
152 $questiondata3->id => array(1 => 1),
153 ), question_engine::load_used_variants(
154 array($questiondata1->id, $questiondata2->id, $questiondata3->id),
155 new qubaid_list(array($quba->get_id()))));
156 }
e900b2f3
TH
157
158 public function test_repeated_usage_saving_new_usage() {
159 global $DB;
160
161 $this->resetAfterTest();
162
163 $initialqurows = $DB->count_records('question_usages');
164 $initialqarows = $DB->count_records('question_attempts');
165 $initialqasrows = $DB->count_records('question_attempt_steps');
166
167 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
168 $cat = $generator->create_question_category();
169 $questiondata1 = $generator->create_question('shortanswer', null, array('category' => $cat->id));
170
171 $quba = question_engine::make_questions_usage_by_activity('test', context_system::instance());
172 $quba->set_preferred_behaviour('deferredfeedback');
173 $quba->add_question(question_bank::load_question($questiondata1->id));
174 $quba->start_all_questions();
175 question_engine::save_questions_usage_by_activity($quba);
176
177 // Check one usage, question_attempts and step added.
178 $firstid = $quba->get_id();
179 $this->assertEquals(1, $DB->count_records('question_usages') - $initialqurows);
180 $this->assertEquals(1, $DB->count_records('question_attempts') - $initialqarows);
181 $this->assertEquals(1, $DB->count_records('question_attempt_steps') - $initialqasrows);
182
183 $quba->finish_all_questions();
184 question_engine::save_questions_usage_by_activity($quba);
185
186 // Check usage id not changed.
187 $this->assertEquals($firstid, $quba->get_id());
188
189 // Check still one usage, question_attempts, but now two steps.
190 $this->assertEquals(1, $DB->count_records('question_usages') - $initialqurows);
191 $this->assertEquals(1, $DB->count_records('question_attempts') - $initialqarows);
192 $this->assertEquals(2, $DB->count_records('question_attempt_steps') - $initialqasrows);
193 }
194
195 public function test_repeated_usage_saving_existing_usage() {
196 global $DB;
197
198 $this->resetAfterTest();
199
200 $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
201 $cat = $generator->create_question_category();
202 $questiondata1 = $generator->create_question('shortanswer', null, array('category' => $cat->id));
203
204 $initquba = question_engine::make_questions_usage_by_activity('test', context_system::instance());
205 $initquba->set_preferred_behaviour('deferredfeedback');
206 $slot = $initquba->add_question(question_bank::load_question($questiondata1->id));
207 $initquba->start_all_questions();
208 question_engine::save_questions_usage_by_activity($initquba);
209
210 $quba = question_engine::load_questions_usage_by_activity($initquba->get_id());
211
212 $initialqurows = $DB->count_records('question_usages');
213 $initialqarows = $DB->count_records('question_attempts');
214 $initialqasrows = $DB->count_records('question_attempt_steps');
215
216 $quba->process_all_actions(time(), $quba->prepare_simulated_post_data(
217 [$slot => ['answer' => 'Frog']]));
218 question_engine::save_questions_usage_by_activity($quba);
219
220 // Check one usage, question_attempts and step added.
221 $this->assertEquals(0, $DB->count_records('question_usages') - $initialqurows);
222 $this->assertEquals(0, $DB->count_records('question_attempts') - $initialqarows);
223 $this->assertEquals(1, $DB->count_records('question_attempt_steps') - $initialqasrows);
224
225 $quba->finish_all_questions();
226 question_engine::save_questions_usage_by_activity($quba);
227
228 // Check still one usage, question_attempts, but now two steps.
229 $this->assertEquals(0, $DB->count_records('question_usages') - $initialqurows);
230 $this->assertEquals(0, $DB->count_records('question_attempts') - $initialqarows);
231 $this->assertEquals(2, $DB->count_records('question_attempt_steps') - $initialqasrows);
232 }
a3624fdf
TH
233
234 /**
235 * Test that database operations on an empty usage work without errors.
236 */
237 public function test_save_and_load_an_empty_usage() {
238 $this->resetAfterTest();
239
240 // Create a new usage.
241 $quba = question_engine::make_questions_usage_by_activity('test', context_system::instance());
242 $quba->set_preferred_behaviour('deferredfeedback');
243
244 // Save it.
245 question_engine::save_questions_usage_by_activity($quba);
246
247 // Reload it.
248 $reloadedquba = question_engine::load_questions_usage_by_activity($quba->get_id());
249 $this->assertCount(0, $quba->get_slots());
250
251 // Delete it.
252 question_engine::delete_questions_usage_by_activity($quba->get_id());
253 }
cf256c05 254}