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 qbank_usage;
18
 
19
defined('MOODLE_INTERNAL') || die();
20
 
21
use mod_quiz\quiz_attempt;
22
 
23
global $CFG;
24
require_once($CFG->dirroot . '/mod/quiz/tests/quiz_question_helper_test_trait.php');
25
 
26
/**
27
 * Helper test.
28
 *
29
 * @package    qbank_usage
30
 * @copyright  2021 Catalyst IT Australia Pty Ltd
31
 * @author     Safat Shahin <safatshahin@catalyst-au.net>
32
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33
 * @coversDefaultClass \qbank_usage\helper
34
 */
35
class helper_test extends \advanced_testcase {
36
 
37
    use \quiz_question_helper_test_trait;
38
 
39
    /**
40
     * @var \stdClass $quiz
41
     */
42
    protected $quiz;
43
 
44
    /**
45
     * @var \stdClass $user
46
     */
47
    protected $user;
48
 
49
    /**
50
     * @var \core_question_generator $questiongenerator
51
     */
52
    protected $questiongenerator;
53
 
54
    /**
55
     * @var array $questions
56
     */
57
    protected $questions = [];
58
 
59
    /**
60
     * Test setup.
61
     */
62
    public function setup(): void {
63
        $this->resetAfterTest();
64
        $layout = '1,2,0';
65
        // Make a user to do the quiz.
66
        $this->user = $this->getDataGenerator()->create_user();
67
        $course = $this->getDataGenerator()->create_course();
68
        // Make a quiz.
69
        $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
70
        $this->quiz = $quizgenerator->create_instance(['course' => $course->id,
71
                'grade' => 100.0, 'sumgrades' => 2, 'layout' => $layout]);
72
 
73
        $this->questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
74
        $cat = $this->questiongenerator->create_question_category();
75
 
76
        $page = 1;
77
        foreach (explode(',', $layout) as $slot) {
78
            if ($slot == 0) {
79
                $page += 1;
80
                continue;
81
            }
82
 
83
            $question = $this->questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
84
            quiz_add_quiz_question($question->id, $this->quiz, $page);
85
            $this->questions [] = $question;
86
        }
87
    }
88
 
89
    /**
90
     * Record a quiz attempt.
91
     *
92
     * @return void
93
     */
94
    protected function attempt_quiz(): void {
95
        $quizobj = \mod_quiz\quiz_settings::create($this->quiz->id, $this->user->id);
96
 
97
        $quba = \question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
98
        $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);
99
        $timenow = time();
100
        $attempt = quiz_create_attempt($quizobj, 1, false, $timenow, false, $this->user->id);
101
        quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow);
102
        quiz_attempt_save_started($quizobj, $quba, $attempt);
103
        quiz_attempt::create($attempt->id);
104
    }
105
 
106
    /**
107
     * Test question attempt count.
108
     *
109
     * @covers ::get_question_attempts_count_in_quiz
110
     */
11 efrain 111
    public function test_get_question_attempts_count_in_quiz(): void {
1 efrain 112
        $this->attempt_quiz();
113
        foreach ($this->questions as $question) {
114
            $questionattemptcount = helper::get_question_attempts_count_in_quiz($question->id, $this->quiz->id);
115
            // Test the attempt count matches the usage count, each question should have one count.
116
            $this->assertEquals(1, $questionattemptcount);
117
        }
118
    }
119
 
120
    /**
121
     * Test test usage data.
122
     *
123
     * @covers ::get_question_entry_usage_count
124
     */
11 efrain 125
    public function test_get_question_entry_usage_count(): void {
1 efrain 126
        foreach ($this->questions as $question) {
127
            $count = helper::get_question_entry_usage_count(\question_bank::load_question($question->id));
128
            // Test that the attempt data matches the usage data for the count.
129
            $this->assertEquals(1, $count);
130
        }
131
    }
132
 
133
    /**
134
     * If a question has been included via a random question attempt, this should be counted as a usage.
135
     *
136
     * @covers ::get_question_entry_usage_count
137
     * @return void
138
     */
139
    public function test_get_random_question_attempts_usage_count(): void {
140
        $this->setAdminUser();
141
        $cat = $this->questiongenerator->create_question_category();
142
        $question = $this->questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
143
        $this->add_random_questions($this->quiz->id, 1, $cat->id, 1);
144
 
145
        $qdef = \question_bank::load_question($question->id);
146
        $count = helper::get_question_entry_usage_count($qdef);
147
        $this->assertEquals(0, $count);
148
 
149
        $this->attempt_quiz();
150
 
151
        $count = helper::get_question_entry_usage_count($qdef);
152
        $this->assertEquals(1, $count);
153
    }
154
 
155
    /**
156
     * When a question referenced directly is edited, the usage count of all versions remains the same.
157
     *
158
     * When checking usage of separate versions, the new version should show usages but the original version should not.
159
     *
160
     * @covers ::get_question_entry_usage_count
161
     * @return void
162
     */
163
    public function test_edited_question_usage_counts(): void {
164
        foreach ($this->questions as $question) {
165
            $qdef = \question_bank::load_question($question->id);
166
            $count1 = helper::get_question_entry_usage_count($qdef);
167
            // Each question should have 1 usage.
168
            $this->assertEquals(1, $count1);
169
 
170
            $newversion = $this->questiongenerator->update_question($question);
171
            $newqdef = \question_bank::load_question($newversion->id);
172
 
173
            // Either version should return the same count if not checking a specific version.
174
            $count2 = helper::get_question_entry_usage_count($qdef);
175
            $this->assertEquals(1, $count2);
176
            $count3 = helper::get_question_entry_usage_count($newqdef);
177
            $this->assertEquals(1, $count3);
178
            // Checking the specific version count should return the counts for each version.
179
            // The original version is no longer included in the quiz, so has 0 usages.
180
            $count4 = helper::get_question_entry_usage_count($qdef, true);
181
            $this->assertEquals(0, $count4);
182
            // The new version is now included in the quiz, so has 1 usage.
183
            $count5 = helper::get_question_entry_usage_count($newqdef, true);
184
            $this->assertEquals(1, $count5);
185
        }
186
    }
187
 
188
    /**
189
     * When a question referenced directly with attempts is edited, the usage count of all versions remains the same.
190
     *
191
     * When checking usage of separate versions, both versions should show usage.
192
     *
193
     * @covers ::get_question_entry_usage_count
194
     * @return void
195
     */
196
    public function test_edited_attempted_question_usage_counts(): void {
197
        $this->attempt_quiz();
198
 
199
        foreach ($this->questions as $question) {
200
            $qdef = \question_bank::load_question($question->id);
201
            $count1 = helper::get_question_entry_usage_count($qdef);
202
            // Each question should have 1 usage.
203
            $this->assertEquals(1, $count1);
204
 
205
            $newversion = $this->questiongenerator->update_question($question);
206
            $newqdef = \question_bank::load_question($newversion->id);
207
 
208
            // Either version should return the same count if not checking a specific version.
209
            $count2 = helper::get_question_entry_usage_count($qdef);
210
            $this->assertEquals(1, $count2);
211
            $count3 = helper::get_question_entry_usage_count($newqdef);
212
            $this->assertEquals(1, $count3);
213
            // Checking the specific version count should return the counts for each version.
214
            // The original version is no longer included in the quiz. However, the is still an attempt using this question version,
215
            // so it has 1 usage.
216
            $count4 = helper::get_question_entry_usage_count($qdef, true);
217
            $this->assertEquals(1, $count4);
218
            // The new version is now included in the quiz, so has 1 usage.
219
            $count5 = helper::get_question_entry_usage_count($newqdef, true);
220
            $this->assertEquals(1, $count5);
221
        }
222
    }
223
 
224
    /**
225
     * When a random question with attempts is edited, it should still have the same usage count.
226
     *
227
     * When checking usage of separate versions, the original version should still show usage but the new version should not.
228
     *
229
     * @covers ::get_question_entry_usage_count
230
     * @return void
231
     */
232
    public function test_edited_attempted_random_question_usage_count(): void {
233
        $this->setAdminUser();
234
        $cat = $this->questiongenerator->create_question_category();
235
        $question = $this->questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
236
        $this->add_random_questions($this->quiz->id, 1, $cat->id, 1);
237
 
238
        $this->attempt_quiz();
239
 
240
        $qdef = \question_bank::load_question($question->id);
241
        $count1 = helper::get_question_entry_usage_count($qdef);
242
        $this->assertEquals(1, $count1);
243
 
244
        $newversion = $this->questiongenerator->update_question($question);
245
        $newqdef = \question_bank::load_question($newversion->id);
246
 
247
        // Either version should return the same count if not checking a specific version.
248
        $count2 = helper::get_question_entry_usage_count($qdef);
249
        $this->assertEquals(1, $count2);
250
        $count3 = helper::get_question_entry_usage_count($newqdef);
251
        $this->assertEquals(1, $count3);
252
        // Checking the specific version count should return the counts for each version.
253
        // There is still an attempt of the original version has part of the random question attempt, so it has 1 usage.
254
        $count4 = helper::get_question_entry_usage_count($qdef, true);
255
        $this->assertEquals(1, $count4);
256
        // There is no attempt of the new version, so it has 0 usages.
257
        $count5 = helper::get_question_entry_usage_count($newqdef, true);
258
        $this->assertEquals(0, $count5);
259
    }
260
}