2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * Quiz attempt walk through tests.
22 * @copyright 2013 The Open University
23 * @author Jamie Pratt <me@jamiep.org>
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 defined('MOODLE_INTERNAL') || die();
30 require_once($CFG->dirroot . '/mod/quiz/locallib.php');
33 * Quiz attempt walk through.
37 * @copyright 2013 The Open University
38 * @author Jamie Pratt <me@jamiep.org>
39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41 class mod_quiz_attempt_walkthrough_testcase extends advanced_testcase {
44 * Create a quiz with questions and walk through a quiz attempt.
46 public function test_quiz_attempt_walkthrough() {
49 $this->resetAfterTest(true);
52 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
54 $quiz = $quizgenerator->create_instance(array('course'=>$SITE->id, 'questionsperpage' => 0, 'grade' => 100.0,
57 // Create a couple of questions.
58 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
60 $cat = $questiongenerator->create_question_category();
61 $saq = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
62 $numq = $questiongenerator->create_question('numerical', null, array('category' => $cat->id));
64 // Add them to the quiz.
65 quiz_add_quiz_question($saq->id, $quiz);
66 quiz_add_quiz_question($numq->id, $quiz);
68 // Make a user to do the quiz.
69 $user1 = $this->getDataGenerator()->create_user();
71 $quizobj = quiz::create($quiz->id, $user1->id);
74 $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
75 $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
78 $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $user1->id);
80 quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow);
81 $this->assertEquals('1,2,0', $attempt->layout);
83 quiz_attempt_save_started($quizobj, $quba, $attempt);
85 // Process some responses from the student.
86 $attemptobj = quiz_attempt::create($attempt->id);
87 $this->assertFalse($attemptobj->has_response_to_at_least_one_graded_question());
89 $prefix1 = $quba->get_field_prefix(1);
90 $prefix2 = $quba->get_field_prefix(2);
92 $tosubmit = array(1 => array('answer' => 'frog'),
93 2 => array('answer' => '3.14'));
95 $attemptobj->process_submitted_actions($timenow, false, $tosubmit);
97 // Finish the attempt.
98 $attemptobj = quiz_attempt::create($attempt->id);
99 $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question());
100 $attemptobj->process_finish($timenow, false);
102 // Re-load quiz attempt data.
103 $attemptobj = quiz_attempt::create($attempt->id);
105 // Check that results are stored as expected.
106 $this->assertEquals(1, $attemptobj->get_attempt_number());
107 $this->assertEquals(2, $attemptobj->get_sum_marks());
108 $this->assertEquals(true, $attemptobj->is_finished());
109 $this->assertEquals($timenow, $attemptobj->get_submitted_date());
110 $this->assertEquals($user1->id, $attemptobj->get_userid());
111 $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question());
113 // Check quiz grades.
114 $grades = quiz_get_user_grades($quiz, $user1->id);
115 $grade = array_shift($grades);
116 $this->assertEquals(100.0, $grade->rawgrade);
119 $gradebookgrades = grade_get_grades($SITE->id, 'mod', 'quiz', $quiz->id, $user1->id);
120 $gradebookitem = array_shift($gradebookgrades->items);
121 $gradebookgrade = array_shift($gradebookitem->grades);
122 $this->assertEquals(100, $gradebookgrade->grade);
126 * Create a quiz with a random as well as other questions and walk through quiz attempts.
128 public function test_quiz_with_random_question_attempt_walkthrough() {
131 $this->resetAfterTest(true);
132 question_bank::get_qtype('random')->clear_caches_before_testing();
134 $this->setAdminUser();
137 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
139 $quiz = $quizgenerator->create_instance(array('course' => $SITE->id, 'questionsperpage' => 2, 'grade' => 100.0,
142 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
144 // Add two questions to question category.
145 $cat = $questiongenerator->create_question_category();
146 $saq = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));
147 $numq = $questiongenerator->create_question('numerical', null, array('category' => $cat->id));
149 // Add random question to the quiz.
150 quiz_add_random_questions($quiz, 0, $cat->id, 1, false);
152 // Make another category.
153 $cat2 = $questiongenerator->create_question_category();
154 $match = $questiongenerator->create_question('match', null, array('category' => $cat->id));
156 quiz_add_quiz_question($match->id, $quiz, 0);
158 $multichoicemulti = $questiongenerator->create_question('multichoice', 'two_of_four', array('category' => $cat->id));
160 quiz_add_quiz_question($multichoicemulti->id, $quiz, 0);
162 $multichoicesingle = $questiongenerator->create_question('multichoice', 'one_of_four', array('category' => $cat->id));
164 quiz_add_quiz_question($multichoicesingle->id, $quiz, 0);
166 foreach (array($saq->id => 'frog', $numq->id => '3.14') as $randomqidtoselect => $randqanswer) {
167 // Make a new user to do the quiz each loop.
168 $user1 = $this->getDataGenerator()->create_user();
169 $this->setUser($user1);
171 $quizobj = quiz::create($quiz->id, $user1->id);
173 // Start the attempt.
174 $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
175 $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
178 $attempt = quiz_create_attempt($quizobj, 1, false, $timenow);
180 quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow, array(1 => $randomqidtoselect));
181 $this->assertEquals('1,2,0,3,4,0', $attempt->layout);
183 quiz_attempt_save_started($quizobj, $quba, $attempt);
185 // Process some responses from the student.
186 $attemptobj = quiz_attempt::create($attempt->id);
187 $this->assertFalse($attemptobj->has_response_to_at_least_one_graded_question());
190 $selectedquestionid = $quba->get_question_attempt(1)->get_question()->id;
191 $tosubmit[1] = array('answer' => $randqanswer);
192 $tosubmit[2] = array(
193 'frog' => 'amphibian',
195 'newt' => 'amphibian');
196 $tosubmit[3] = array('One' => '1', 'Two' => '0', 'Three' => '1', 'Four' => '0'); // First and third choice.
197 $tosubmit[4] = array('answer' => 'One'); // The first choice.
199 $attemptobj->process_submitted_actions($timenow, false, $tosubmit);
201 // Finish the attempt.
202 $attemptobj = quiz_attempt::create($attempt->id);
203 $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question());
204 $attemptobj->process_finish($timenow, false);
206 // Re-load quiz attempt data.
207 $attemptobj = quiz_attempt::create($attempt->id);
209 // Check that results are stored as expected.
210 $this->assertEquals(1, $attemptobj->get_attempt_number());
211 $this->assertEquals(4, $attemptobj->get_sum_marks());
212 $this->assertEquals(true, $attemptobj->is_finished());
213 $this->assertEquals($timenow, $attemptobj->get_submitted_date());
214 $this->assertEquals($user1->id, $attemptobj->get_userid());
215 $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question());
217 // Check quiz grades.
218 $grades = quiz_get_user_grades($quiz, $user1->id);
219 $grade = array_shift($grades);
220 $this->assertEquals(100.0, $grade->rawgrade);
223 $gradebookgrades = grade_get_grades($SITE->id, 'mod', 'quiz', $quiz->id, $user1->id);
224 $gradebookitem = array_shift($gradebookgrades->items);
225 $gradebookgrade = array_shift($gradebookitem->grades);
226 $this->assertEquals(100, $gradebookgrade->grade);
231 public function get_correct_response_for_variants() {
232 return array(array(1, 9.9), array(2, 8.5), array(5, 14.2), array(10, 6.8, true));
235 protected $quizwithvariants = null;
238 * Create a quiz with a single question with variants and walk through quiz attempts.
240 * @dataProvider get_correct_response_for_variants
242 public function test_quiz_with_question_with_variants_attempt_walkthrough($variantno, $correctresponse, $done = false) {
245 $this->resetAfterTest($done);
247 $this->setAdminUser();
249 if ($this->quizwithvariants === null) {
251 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
253 $this->quizwithvariants = $quizgenerator->create_instance(array('course'=>$SITE->id,
254 'questionsperpage' => 0,
258 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
260 $cat = $questiongenerator->create_question_category();
261 $calc = $questiongenerator->create_question('calculatedsimple', 'sumwithvariants', array('category' => $cat->id));
262 quiz_add_quiz_question($calc->id, $this->quizwithvariants, 0);
266 // Make a new user to do the quiz.
267 $user1 = $this->getDataGenerator()->create_user();
268 $this->setUser($user1);
269 $quizobj = quiz::create($this->quizwithvariants->id, $user1->id);
271 // Start the attempt.
272 $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
273 $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
276 $attempt = quiz_create_attempt($quizobj, 1, false, $timenow);
279 quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow, array(), array(1 => $variantno));
280 $this->assertEquals('1,0', $attempt->layout);
281 quiz_attempt_save_started($quizobj, $quba, $attempt);
283 // Process some responses from the student.
284 $attemptobj = quiz_attempt::create($attempt->id);
285 $this->assertFalse($attemptobj->has_response_to_at_least_one_graded_question());
287 $tosubmit = array(1 => array('answer' => $correctresponse));
288 $attemptobj->process_submitted_actions($timenow, false, $tosubmit);
290 // Finish the attempt.
291 $attemptobj = quiz_attempt::create($attempt->id);
292 $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question());
294 $attemptobj->process_finish($timenow, false);
296 // Re-load quiz attempt data.
297 $attemptobj = quiz_attempt::create($attempt->id);
299 // Check that results are stored as expected.
300 $this->assertEquals(1, $attemptobj->get_attempt_number());
301 $this->assertEquals(1, $attemptobj->get_sum_marks());
302 $this->assertEquals(true, $attemptobj->is_finished());
303 $this->assertEquals($timenow, $attemptobj->get_submitted_date());
304 $this->assertEquals($user1->id, $attemptobj->get_userid());
305 $this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question());
307 // Check quiz grades.
308 $grades = quiz_get_user_grades($this->quizwithvariants, $user1->id);
309 $grade = array_shift($grades);
310 $this->assertEquals(100.0, $grade->rawgrade);
313 $gradebookgrades = grade_get_grades($SITE->id, 'mod', 'quiz', $this->quizwithvariants->id, $user1->id);
314 $gradebookitem = array_shift($gradebookgrades->items);
315 $gradebookgrade = array_shift($gradebookitem->grades);
316 $this->assertEquals(100, $gradebookgrade->grade);