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