See Release Notes
Long Term Support Release
<?php // This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see <http://www.gnu.org/licenses/>. /** * Contains the class containing unit tests for the quiz notify attempt manual grading completed cron task. * * @package mod_quiz * @copyright 2021 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace mod_quiz; use advanced_testcase; use context_course; use context_module; use mod_quiz\task\quiz_notify_attempt_manual_grading_completed; use question_engine;< use quiz; < use quiz_attempt;> use mod_quiz\quiz_settings;use stdClass; defined('MOODLE_INTERNAL') || die(); /** * Class containing unit tests for the quiz notify attempt manual grading completed cron task. * * @package mod_quiz * @copyright 2021 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class quiz_notify_attempt_manual_grading_completed_test extends advanced_testcase { /** @var \stdClass $course Test course to contain quiz. */ protected $course; /** @var \stdClass $quiz A test quiz. */ protected $quiz; /** @var context The quiz context. */ protected $context; /** @var stdClass The course_module. */ protected $cm; /** @var stdClass The student test. */ protected $student; /** @var stdClass The teacher test. */ protected $teacher;< /** @var quiz Object containing the quiz settings. */> /** @var quiz_settings Object containing the quiz settings. */protected $quizobj; /** @var question_usage_by_activity The question usage for this quiz attempt. */ protected $quba; /** * Standard test setup. * * Create a course with a quiz and a student and a(n editing) teacher. * the quiz has a truefalse question and an essay question. * * Also create some bits of a quiz attempt to be used later. */ public function setUp(): void { global $DB; $this->resetAfterTest(); $this->setAdminUser(); // Setup test data. $this->course = $this->getDataGenerator()->create_course(); $this->quiz = $this->getDataGenerator()->create_module('quiz', ['course' => $this->course->id]); $this->context = context_module::instance($this->quiz->cmid); $this->cm = get_coursemodule_from_instance('quiz', $this->quiz->id); // Create users. $this->student = self::getDataGenerator()->create_user(); $this->teacher = self::getDataGenerator()->create_user(); // Users enrolments. $studentrole = $DB->get_record('role', ['shortname' => 'student']); $teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher']); // Allow student to receive messages. $coursecontext = context_course::instance($this->course->id); assign_capability('mod/quiz:emailnotifyattemptgraded', CAP_ALLOW, $studentrole->id, $coursecontext, true); $this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $studentrole->id); $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $teacherrole->id); // Make a quiz. $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); $this->quiz = $quizgenerator->create_instance(['course' => $this->course->id, 'questionsperpage' => 0, 'grade' => 100.0, 'sumgrades' => 2]); // Create a truefalse question and an essay question. $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); $cat = $questiongenerator->create_question_category(); $truefalse = $questiongenerator->create_question('truefalse', null, ['category' => $cat->id]); $essay = $questiongenerator->create_question('essay', null, ['category' => $cat->id]); // Add them to the quiz. quiz_add_quiz_question($truefalse->id, $this->quiz); quiz_add_quiz_question($essay->id, $this->quiz);< $this->quizobj = quiz::create($this->quiz->id);> $this->quizobj = quiz_settings::create($this->quiz->id);$this->quba = question_engine::make_questions_usage_by_activity('mod_quiz', $this->quizobj->get_context()); $this->quba->set_preferred_behaviour($this->quizobj->get_quiz()->preferredbehaviour); } /** * Test SQL querry get list attempt in condition. */ public function test_get_list_of_attempts_within_conditions() { global $DB; $timenow = time(); // Create an attempt to be completely graded (one hour ago). $attempt1 = quiz_create_attempt($this->quizobj, 1, null, $timenow - HOURSECS, false, $this->student->id); quiz_start_new_attempt($this->quizobj, $this->quba, $attempt1, 1, $timenow - HOURSECS); quiz_attempt_save_started($this->quizobj, $this->quba, $attempt1); // Process some responses from the student (30 mins ago) and submit (20 mins ago). $attemptobj1 = quiz_attempt::create($attempt1->id); $tosubmit = [2 => ['answer' => 'Student 1 answer', 'answerformat' => FORMAT_HTML]]; $attemptobj1->process_submitted_actions($timenow - 30 * MINSECS, false, $tosubmit); $attemptobj1->process_finish($timenow - 20 * MINSECS, false); // Finish the attempt of student (now). $attemptobj1->get_question_usage()->manual_grade(2, 'Good!', 1, FORMAT_HTML); question_engine::save_questions_usage_by_activity($attemptobj1->get_question_usage()); $update = new stdClass(); $update->id = $attemptobj1->get_attemptid(); $update->timemodified = $timenow; $update->sumgrades = $attemptobj1->get_question_usage()->get_total_mark(); $DB->update_record('quiz_attempts', $update);< quiz_save_best_grade($attemptobj1->get_quiz(), $this->student->id);> $attemptobj1->get_quizobj()->get_grade_calculator()->recompute_final_grade();// Not quite time to send yet. $task = new quiz_notify_attempt_manual_grading_completed(); $task->set_time_for_testing($timenow + 5 * HOURSECS - 1); $attempts = $task->get_list_of_attempts(); $this->assertEquals(0, iterator_count($attempts)); // After time to send. $task->set_time_for_testing($timenow + 5 * HOURSECS + 1); $attempts = $task->get_list_of_attempts(); $this->assertEquals(1, iterator_count($attempts)); } /** * Test SQL query does not return attempts if the grading is not complete yet. */ public function test_get_list_of_attempts_without_manual_graded() { $timenow = time(); // Create an attempt which won't be graded (1 hour ago). $attempt2 = quiz_create_attempt($this->quizobj, 2, null, $timenow - HOURSECS, false, $this->student->id); quiz_start_new_attempt($this->quizobj, $this->quba, $attempt2, 2, $timenow - HOURSECS); quiz_attempt_save_started($this->quizobj, $this->quba, $attempt2); // Process some responses from the student (30 mins ago) and submit (now). $attemptobj2 = quiz_attempt::create($attempt2->id); $tosubmit = [2 => ['answer' => 'Answer of student 2.', 'answerformat' => FORMAT_HTML]]; $attemptobj2->process_submitted_actions($timenow - 30 * MINSECS, false, $tosubmit); $attemptobj2->process_finish($timenow, false); // After time to notify, except attempt not graded, so it won't appear. $task = new quiz_notify_attempt_manual_grading_completed(); $task->set_time_for_testing($timenow + 5 * HOURSECS + 1); $attempts = $task->get_list_of_attempts(); $this->assertEquals(0, iterator_count($attempts)); } /** * Test notify manual grading completed task which the user attempt has not capability. */ public function test_notify_manual_grading_completed_task_without_capability() { global $DB; // Create an attempt for a user without the capability. $timenow = time(); $attempt = quiz_create_attempt($this->quizobj, 3, null, $timenow, false, $this->teacher->id); quiz_start_new_attempt($this->quizobj, $this->quba, $attempt, 3, $timenow - HOURSECS); quiz_attempt_save_started($this->quizobj, $this->quba, $attempt); // Process some responses and submit. $attemptobj = quiz_attempt::create($attempt->id); $tosubmit = [2 => ['answer' => 'Answer of teacher.', 'answerformat' => FORMAT_HTML]]; $attemptobj->process_submitted_actions($timenow - 30 * MINSECS, false, $tosubmit); $attemptobj->process_finish($timenow - 20 * MINSECS, false); // Grade the attempt. $attemptobj->get_question_usage()->manual_grade(2, 'Good!', 1, FORMAT_HTML); question_engine::save_questions_usage_by_activity($attemptobj->get_question_usage()); $update = new stdClass(); $update->id = $attemptobj->get_attemptid(); $update->timemodified = $timenow; $update->sumgrades = $attemptobj->get_question_usage()->get_total_mark(); $DB->update_record('quiz_attempts', $update);< quiz_save_best_grade($attemptobj->get_quiz(), $this->student->id);> $attemptobj->get_quizobj()->get_grade_calculator()->recompute_final_grade();// Run the quiz notify attempt manual graded task. ob_start(); $task = new quiz_notify_attempt_manual_grading_completed(); $task->set_time_for_testing($timenow + 5 * HOURSECS + 1); $task->execute(); ob_get_clean(); $attemptobj = quiz_attempt::create($attempt->id); $this->assertEquals($attemptobj->get_attempt()->timefinish, $attemptobj->get_attempt()->gradednotificationsenttime); } /** * Test notify manual grading completed task which the user attempt has capability. */ public function test_notify_manual_grading_completed_task_with_capability() { global $DB; // Create an attempt with capability. $timenow = time(); $attempt = quiz_create_attempt($this->quizobj, 4, null, $timenow, false, $this->student->id); quiz_start_new_attempt($this->quizobj, $this->quba, $attempt, 4, $timenow - HOURSECS); quiz_attempt_save_started($this->quizobj, $this->quba, $attempt); // Process some responses from the student. $attemptobj = quiz_attempt::create($attempt->id); $tosubmit = [2 => ['answer' => 'Answer of student.', 'answerformat' => FORMAT_HTML]]; $attemptobj->process_submitted_actions($timenow - 30 * MINSECS, false, $tosubmit); $attemptobj->process_finish($timenow - 20 * MINSECS, false); // Finish the attempt of student. $attemptobj->get_question_usage()->manual_grade(2, 'Good!', 1, FORMAT_HTML); question_engine::save_questions_usage_by_activity($attemptobj->get_question_usage()); $update = new stdClass(); $update->id = $attemptobj->get_attemptid(); $update->timemodified = $timenow; $update->sumgrades = $attemptobj->get_question_usage()->get_total_mark(); $DB->update_record('quiz_attempts', $update);< quiz_save_best_grade($attemptobj->get_quiz(), $this->student->id);> $attemptobj->get_quizobj()->get_grade_calculator()->recompute_final_grade();// Run the quiz notify attempt manual graded task. ob_start(); $task = new quiz_notify_attempt_manual_grading_completed(); $task->set_time_for_testing($timenow + 5 * HOURSECS + 1); $task->execute(); ob_get_clean(); $attemptobj = quiz_attempt::create($attempt->id); $this->assertNotEquals(null, $attemptobj->get_attempt()->gradednotificationsenttime); $this->assertNotEquals($attemptobj->get_attempt()->timefinish, $attemptobj->get_attempt()->gradednotificationsenttime); } }