Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | 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
/**
18
 * Contains the class containing unit tests for the quiz notify attempt manual grading completed cron task.
19
 *
20
 * @package   mod_quiz
21
 * @copyright 2021 The Open University
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace mod_quiz;
26
 
27
use advanced_testcase;
28
use context_course;
29
use context_module;
30
use mod_quiz\task\quiz_notify_attempt_manual_grading_completed;
31
use question_engine;
32
use mod_quiz\quiz_settings;
33
use stdClass;
34
 
35
defined('MOODLE_INTERNAL') || die();
36
 
37
 
38
/**
39
 * Class containing unit tests for the quiz notify attempt manual grading completed cron task.
40
 *
41
 * @package mod_quiz
42
 * @copyright 2021 The Open University
43
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
44
 */
45
class quiz_notify_attempt_manual_grading_completed_test extends advanced_testcase {
46
    /** @var \stdClass $course Test course to contain quiz. */
47
    protected $course;
48
 
49
    /** @var \stdClass $quiz A test quiz. */
50
    protected $quiz;
51
 
52
    /** @var context The quiz context. */
53
    protected $context;
54
 
55
    /** @var stdClass The course_module. */
56
    protected $cm;
57
 
58
    /** @var stdClass The student test. */
59
    protected $student;
60
 
61
    /** @var stdClass The teacher test. */
62
    protected $teacher;
63
 
64
    /** @var quiz_settings Object containing the quiz settings. */
65
    protected $quizobj;
66
 
67
    /** @var question_usage_by_activity The question usage for this quiz attempt. */
68
    protected $quba;
69
 
70
    /**
71
     * Standard test setup.
72
     *
73
     * Create a course with a quiz and a student and a(n editing) teacher.
74
     * the quiz has a truefalse question and an essay question.
75
     *
76
     * Also create some bits of a quiz attempt to be used later.
77
     */
78
    public function setUp(): void {
79
        global $DB;
80
 
81
        $this->resetAfterTest();
82
        $this->setAdminUser();
83
 
84
        // Setup test data.
85
        $this->course = $this->getDataGenerator()->create_course();
86
        $this->quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $this->course->id]);
87
        $this->context = context_module::instance($this->quiz->cmid);
88
        $this->cm = get_coursemodule_from_instance('quiz', $this->quiz->id);
89
 
90
        // Create users.
91
        $this->student = self::getDataGenerator()->create_user();
92
        $this->teacher = self::getDataGenerator()->create_user();
93
 
94
        // Users enrolments.
95
        $studentrole = $DB->get_record('role', ['shortname' => 'student']);
96
        $teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']);
97
 
98
        // Allow student to receive messages.
99
        $coursecontext = context_course::instance($this->course->id);
100
        assign_capability('mod/quiz:emailnotifyattemptgraded', CAP_ALLOW, $studentrole->id, $coursecontext, true);
101
 
102
        $this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $studentrole->id);
103
        $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $teacherrole->id);
104
 
105
        // Make a quiz.
106
        $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');
107
        $this->quiz = $quizgenerator->create_instance(['course' => $this->course->id, 'questionsperpage' => 0,
108
            'grade' => 100.0, 'sumgrades' => 2]);
109
 
110
        // Create a truefalse question and an essay question.
111
        $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
112
        $cat = $questiongenerator->create_question_category();
113
        $truefalse = $questiongenerator->create_question('truefalse', null, ['category' => $cat->id]);
114
        $essay = $questiongenerator->create_question('essay', null, ['category' => $cat->id]);
115
 
116
        // Add them to the quiz.
117
        quiz_add_quiz_question($truefalse->id, $this->quiz);
118
        quiz_add_quiz_question($essay->id, $this->quiz);
119
 
120
        $this->quizobj = quiz_settings::create($this->quiz->id);
121
        $this->quba = question_engine::make_questions_usage_by_activity('mod_quiz', $this->quizobj->get_context());
122
        $this->quba->set_preferred_behaviour($this->quizobj->get_quiz()->preferredbehaviour);
123
    }
124
 
125
    /**
126
     * Test SQL querry get list attempt in condition.
127
     */
128
    public function test_get_list_of_attempts_within_conditions() {
129
        global $DB;
130
 
131
        $timenow = time();
132
 
133
        // Create an attempt to be completely graded (one hour ago).
134
        $attempt1 = quiz_create_attempt($this->quizobj, 1, null, $timenow - HOURSECS, false, $this->student->id);
135
        quiz_start_new_attempt($this->quizobj, $this->quba, $attempt1, 1, $timenow - HOURSECS);
136
        quiz_attempt_save_started($this->quizobj, $this->quba, $attempt1);
137
 
138
        // Process some responses from the student (30 mins ago) and submit (20 mins ago).
139
        $attemptobj1 = quiz_attempt::create($attempt1->id);
140
        $tosubmit = [2 => ['answer' => 'Student 1 answer', 'answerformat' => FORMAT_HTML]];
141
        $attemptobj1->process_submitted_actions($timenow - 30 * MINSECS, false, $tosubmit);
142
        $attemptobj1->process_finish($timenow - 20 * MINSECS, false);
143
 
144
        // Finish the attempt of student (now).
145
        $attemptobj1->get_question_usage()->manual_grade(2, 'Good!', 1, FORMAT_HTML);
146
        question_engine::save_questions_usage_by_activity($attemptobj1->get_question_usage());
147
 
148
        $update = new stdClass();
149
        $update->id = $attemptobj1->get_attemptid();
150
        $update->timemodified = $timenow;
151
        $update->sumgrades = $attemptobj1->get_question_usage()->get_total_mark();
152
        $DB->update_record('quiz_attempts', $update);
153
        $attemptobj1->get_quizobj()->get_grade_calculator()->recompute_final_grade();
154
 
155
        // Not quite time to send yet.
156
        $task = new quiz_notify_attempt_manual_grading_completed();
157
        $task->set_time_for_testing($timenow + 5 * HOURSECS - 1);
158
        $attempts = $task->get_list_of_attempts();
159
        $this->assertEquals(0, iterator_count($attempts));
160
 
161
        // After time to send.
162
        $task->set_time_for_testing($timenow + 5 * HOURSECS + 1);
163
        $attempts = $task->get_list_of_attempts();
164
        $this->assertEquals(1, iterator_count($attempts));
165
    }
166
 
167
    /**
168
     * Test SQL query does not return attempts if the grading is not complete yet.
169
     */
170
    public function test_get_list_of_attempts_without_manual_graded() {
171
 
172
        $timenow = time();
173
 
174
        // Create an attempt which won't be graded (1 hour ago).
175
        $attempt2 = quiz_create_attempt($this->quizobj, 2, null, $timenow - HOURSECS, false, $this->student->id);
176
        quiz_start_new_attempt($this->quizobj, $this->quba, $attempt2, 2, $timenow - HOURSECS);
177
        quiz_attempt_save_started($this->quizobj, $this->quba, $attempt2);
178
 
179
        // Process some responses from the student (30 mins ago) and submit (now).
180
        $attemptobj2 = quiz_attempt::create($attempt2->id);
181
        $tosubmit = [2 => ['answer' => 'Answer of student 2.', 'answerformat' => FORMAT_HTML]];
182
        $attemptobj2->process_submitted_actions($timenow - 30 * MINSECS, false, $tosubmit);
183
        $attemptobj2->process_finish($timenow, false);
184
 
185
        // After time to notify, except attempt not graded, so it won't appear.
186
        $task = new quiz_notify_attempt_manual_grading_completed();
187
        $task->set_time_for_testing($timenow + 5 * HOURSECS + 1);
188
        $attempts = $task->get_list_of_attempts();
189
 
190
        $this->assertEquals(0, iterator_count($attempts));
191
    }
192
 
193
    /**
194
     * Test notify manual grading completed task which the user attempt has not capability.
195
     */
196
    public function test_notify_manual_grading_completed_task_without_capability() {
197
        global $DB;
198
 
199
        // Create an attempt for a user without the capability.
200
        $timenow = time();
201
        $attempt = quiz_create_attempt($this->quizobj, 3, null, $timenow, false, $this->teacher->id);
202
        quiz_start_new_attempt($this->quizobj, $this->quba, $attempt, 3, $timenow - HOURSECS);
203
        quiz_attempt_save_started($this->quizobj, $this->quba, $attempt);
204
 
205
        // Process some responses and submit.
206
        $attemptobj = quiz_attempt::create($attempt->id);
207
        $tosubmit = [2 => ['answer' => 'Answer of teacher.', 'answerformat' => FORMAT_HTML]];
208
        $attemptobj->process_submitted_actions($timenow - 30 * MINSECS, false, $tosubmit);
209
        $attemptobj->process_finish($timenow - 20 * MINSECS, false);
210
 
211
        // Grade the attempt.
212
        $attemptobj->get_question_usage()->manual_grade(2, 'Good!', 1, FORMAT_HTML);
213
        question_engine::save_questions_usage_by_activity($attemptobj->get_question_usage());
214
 
215
        $update = new stdClass();
216
        $update->id = $attemptobj->get_attemptid();
217
        $update->timemodified = $timenow;
218
        $update->sumgrades = $attemptobj->get_question_usage()->get_total_mark();
219
        $DB->update_record('quiz_attempts', $update);
220
        $attemptobj->get_quizobj()->get_grade_calculator()->recompute_final_grade();
221
 
222
        // Run the quiz notify attempt manual graded task.
223
        ob_start();
224
        $task = new quiz_notify_attempt_manual_grading_completed();
225
        $task->set_time_for_testing($timenow + 5 * HOURSECS + 1);
226
        $task->execute();
227
        ob_get_clean();
228
 
229
        $attemptobj = quiz_attempt::create($attempt->id);
230
        $this->assertEquals($attemptobj->get_attempt()->timefinish, $attemptobj->get_attempt()->gradednotificationsenttime);
231
    }
232
 
233
    /**
234
     * Test notify manual grading completed task which the user attempt has capability.
235
     */
236
    public function test_notify_manual_grading_completed_task_with_capability() {
237
        global $DB;
238
 
239
        // Create an attempt with capability.
240
        $timenow = time();
241
        $attempt = quiz_create_attempt($this->quizobj, 4, null, $timenow, false, $this->student->id);
242
        quiz_start_new_attempt($this->quizobj, $this->quba, $attempt, 4, $timenow - HOURSECS);
243
        quiz_attempt_save_started($this->quizobj, $this->quba, $attempt);
244
 
245
        // Process some responses from the student.
246
        $attemptobj = quiz_attempt::create($attempt->id);
247
        $tosubmit = [2 => ['answer' => 'Answer of student.', 'answerformat' => FORMAT_HTML]];
248
        $attemptobj->process_submitted_actions($timenow - 30 * MINSECS, false, $tosubmit);
249
        $attemptobj->process_finish($timenow - 20 * MINSECS, false);
250
 
251
        // Finish the attempt of student.
252
        $attemptobj->get_question_usage()->manual_grade(2, 'Good!', 1, FORMAT_HTML);
253
        question_engine::save_questions_usage_by_activity($attemptobj->get_question_usage());
254
 
255
        $update = new stdClass();
256
        $update->id = $attemptobj->get_attemptid();
257
        $update->timemodified = $timenow;
258
        $update->sumgrades = $attemptobj->get_question_usage()->get_total_mark();
259
        $DB->update_record('quiz_attempts', $update);
260
        $attemptobj->get_quizobj()->get_grade_calculator()->recompute_final_grade();
261
 
262
        // Run the quiz notify attempt manual graded task.
263
        ob_start();
264
        $task = new quiz_notify_attempt_manual_grading_completed();
265
        $task->set_time_for_testing($timenow + 5 * HOURSECS + 1);
266
        $task->execute();
267
        ob_get_clean();
268
 
269
        $attemptobj = quiz_attempt::create($attempt->id);
270
 
271
        $this->assertNotEquals(null, $attemptobj->get_attempt()->gradednotificationsenttime);
272
        $this->assertNotEquals($attemptobj->get_attempt()->timefinish, $attemptobj->get_attempt()->gradednotificationsenttime);
273
    }
274
}