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/>. /** * Unit tests for grade/lib.php. * * @package core_grades * @category test * @copyright 2016 Jun Pataleta * @license http://www.gnu.org/copyleft/gpl.html GNU Public License */> namespace core_grades; > defined('MOODLE_INTERNAL') || die(); > use assign; > use cm_info; global $CFG; > use grade_item; require_once($CFG->dirroot . '/grade/lib.php'); > use grade_plugin_return; > use grade_report_summary;/** * Unit tests for grade/lib.php. * * @package core_grades * @category test * @copyright 2016 Jun Pataleta <jun@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */< class core_grade_lib_test extends advanced_testcase {> class lib_test extends \advanced_testcase {/** * Test can_output_item. */ public function test_can_output_item() { $this->resetAfterTest(); $generator = $this->getDataGenerator(); // Course level grade category. $course = $generator->create_course(); // Grade tree looks something like: // - Test course (Rendered).< $gradetree = grade_category::fetch_course_tree($course->id); < $this->assertTrue(grade_tree::can_output_item($gradetree));> $gradetree = \grade_category::fetch_course_tree($course->id); > $this->assertTrue(\grade_tree::can_output_item($gradetree));// Add a grade category with default settings. $generator->create_grade_category(array('courseid' => $course->id)); // Grade tree now looks something like: // - Test course n (Rendered). // -- Grade category n (Rendered).< $gradetree = grade_category::fetch_course_tree($course->id);> $gradetree = \grade_category::fetch_course_tree($course->id);$this->assertNotEmpty($gradetree['children']); foreach ($gradetree['children'] as $child) {< $this->assertTrue(grade_tree::can_output_item($child));> $this->assertTrue(\grade_tree::can_output_item($child));} // Add a grade category with grade type = None. $nototalcategory = 'No total category'; $nototalparams = [ 'courseid' => $course->id, 'fullname' => $nototalcategory, 'aggregation' => GRADE_AGGREGATE_WEIGHTED_MEAN ]; $nototal = $generator->create_grade_category($nototalparams);< $catnototal = grade_category::fetch(array('id' => $nototal->id));> $catnototal = \grade_category::fetch(array('id' => $nototal->id));// Set the grade type of the grade item associated to the grade category. $catitemnototal = $catnototal->load_grade_item(); $catitemnototal->gradetype = GRADE_TYPE_NONE; $catitemnototal->update(); // Grade tree looks something like: // - Test course n (Rendered). // -- Grade category n (Rendered). // -- No total category (Not rendered).< $gradetree = grade_category::fetch_course_tree($course->id);> $gradetree = \grade_category::fetch_course_tree($course->id);foreach ($gradetree['children'] as $child) { if ($child['object']->fullname == $nototalcategory) {< $this->assertFalse(grade_tree::can_output_item($child));> $this->assertFalse(\grade_tree::can_output_item($child));} else {< $this->assertTrue(grade_tree::can_output_item($child));> $this->assertTrue(\grade_tree::can_output_item($child));} } // Add another grade category with default settings under 'No total category'. $normalinnototalparams = [ 'courseid' => $course->id, 'fullname' => 'Normal category in no total category', 'parent' => $nototal->id ]; $generator->create_grade_category($normalinnototalparams); // Grade tree looks something like: // - Test course n (Rendered). // -- Grade category n (Rendered). // -- No total category (Rendered). // --- Normal category in no total category (Rendered).< $gradetree = grade_category::fetch_course_tree($course->id);> $gradetree = \grade_category::fetch_course_tree($course->id);foreach ($gradetree['children'] as $child) { // All children are now visible.< $this->assertTrue(grade_tree::can_output_item($child));> $this->assertTrue(\grade_tree::can_output_item($child));if (!empty($child['children'])) { foreach ($child['children'] as $grandchild) {< $this->assertTrue(grade_tree::can_output_item($grandchild));> $this->assertTrue(\grade_tree::can_output_item($grandchild));} } } // Add a grade category with grade type = None. $nototalcategory2 = 'No total category 2'; $nototal2params = [ 'courseid' => $course->id, 'fullname' => $nototalcategory2, 'aggregation' => GRADE_AGGREGATE_WEIGHTED_MEAN ]; $nototal2 = $generator->create_grade_category($nototal2params);< $catnototal2 = grade_category::fetch(array('id' => $nototal2->id));> $catnototal2 = \grade_category::fetch(array('id' => $nototal2->id));// Set the grade type of the grade item associated to the grade category. $catitemnototal2 = $catnototal2->load_grade_item(); $catitemnototal2->gradetype = GRADE_TYPE_NONE; $catitemnototal2->update(); // Add a category with no total under 'No total category'. $nototalinnototalcategory = 'Category with no total in no total category'; $nototalinnototalparams = [ 'courseid' => $course->id, 'fullname' => $nototalinnototalcategory, 'aggregation' => GRADE_AGGREGATE_WEIGHTED_MEAN, 'parent' => $nototal2->id ]; $nototalinnototal = $generator->create_grade_category($nototalinnototalparams);< $catnototalinnototal = grade_category::fetch(array('id' => $nototalinnototal->id));> $catnototalinnototal = \grade_category::fetch(array('id' => $nototalinnototal->id));// Set the grade type of the grade item associated to the grade category. $catitemnototalinnototal = $catnototalinnototal->load_grade_item(); $catitemnototalinnototal->gradetype = GRADE_TYPE_NONE; $catitemnototalinnototal->update(); // Grade tree looks something like: // - Test course n (Rendered). // -- Grade category n (Rendered). // -- No total category (Rendered). // --- Normal category in no total category (Rendered). // -- No total category 2 (Not rendered). // --- Category with no total in no total category (Not rendered).< $gradetree = grade_category::fetch_course_tree($course->id);> $gradetree = \grade_category::fetch_course_tree($course->id);foreach ($gradetree['children'] as $child) { if ($child['object']->fullname == $nototalcategory2) {< $this->assertFalse(grade_tree::can_output_item($child));> $this->assertFalse(\grade_tree::can_output_item($child));} else {< $this->assertTrue(grade_tree::can_output_item($child));> $this->assertTrue(\grade_tree::can_output_item($child));} if (!empty($child['children'])) { foreach ($child['children'] as $grandchild) { if ($grandchild['object']->fullname == $nototalinnototalcategory) {< $this->assertFalse(grade_tree::can_output_item($grandchild));> $this->assertFalse(\grade_tree::can_output_item($grandchild)); > } else { > $this->assertTrue(\grade_tree::can_output_item($grandchild)); > } > } > } > } > } > > /** > * Tests that ungraded_counts calculates count and sum of grades correctly when there are graded users. > * > * @covers \grade_report::ungraded_counts > */ > public function test_ungraded_counts_count_sumgrades() { > global $DB; > > $this->resetAfterTest(true); > > $course1 = $this->getDataGenerator()->create_course(); > $course2 = $this->getDataGenerator()->create_course(); > > $studentrole = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST); > $teacherrole = $DB->get_record('role', ['shortname' => 'editingteacher'], '*', MUST_EXIST); > > // Custom roles (gradable and non gradable). > $gradeblerole = create_role('New student role', 'gradable', > 'Gradable role', 'student'); > $nongradeblerole = create_role('New student role', 'nongradable', > 'Non gradable role', 'student'); > > // Set up gradable roles. > set_config('gradebookroles', $studentrole->id . ',' . $gradeblerole); > > // Create users. > > // These will be gradable users. > $student1 = $this->getDataGenerator()->create_user(['username' => 'student1']); > $student2 = $this->getDataGenerator()->create_user(['username' => 'student2']); > $student3 = $this->getDataGenerator()->create_user(['username' => 'student3']); > $student5 = $this->getDataGenerator()->create_user(['username' => 'student5']); > > // These will be non-gradable users. > $student4 = $this->getDataGenerator()->create_user(['username' => 'student4']); > $student6 = $this->getDataGenerator()->create_user(['username' => 'student6']); > $teacher = $this->getDataGenerator()->create_user(['username' => 'teacher']); > > // Enrol students. > $this->getDataGenerator()->enrol_user($student1->id, $course1->id, $studentrole->id); > $this->getDataGenerator()->enrol_user($student2->id, $course1->id, $studentrole->id); > $this->getDataGenerator()->enrol_user($student3->id, $course1->id, $gradeblerole); > > $this->getDataGenerator()->enrol_user($student5->id, $course1->id, $nongradeblerole); > $this->getDataGenerator()->enrol_user($student6->id, $course1->id, $studentrole->id); > $this->getDataGenerator()->enrol_user($teacher->id, $course1->id, $teacherrole->id); > > // User that is enrolled in a different course. > $this->getDataGenerator()->enrol_user($student4->id, $course2->id, $studentrole->id); > > // Mark user as deleted. > $student6->deleted = 1; > $DB->update_record('user', $student6); > > // Create grade items in course 1. > $assign1 = $this->getDataGenerator()->create_module('assign', ['course' => $course1->id]); > $assign2 = $this->getDataGenerator()->create_module('assign', ['course' => $course1->id]); > $quiz1 = $this->getDataGenerator()->create_module('quiz', ['course' => $course1->id]); > > $manuaitem = new \grade_item($this->getDataGenerator()->create_grade_item([ > 'itemname' => 'Grade item1', > 'idnumber' => 'git1', > 'courseid' => $course1->id, > ])); > > // Create grade items in course 2. > $assign3 = $this->getDataGenerator()->create_module('assign', ['course' => $course2->id]); > > // Grade users in first course. > $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign1->id)); > $assigninstance = new assign($cm->context, $cm, $course1); > $grade = $assigninstance->get_user_grade($student1->id, true); > $grade->grade = 40; > $assigninstance->update_grade($grade); > > $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign2->id)); > $assigninstance = new assign($cm->context, $cm, $course1); > $grade = $assigninstance->get_user_grade($student3->id, true); > $grade->grade = 50; > $assigninstance->update_grade($grade); > > // Override grade for assignment in gradebook. > $gi = \grade_item::fetch([ > 'itemtype' => 'mod', > 'itemmodule' => 'assign', > 'iteminstance' => $cm->instance, > 'courseid' => $course1->id > ]); > $gi->update_final_grade($student3->id, 55); > > // Grade user in second course. > $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign3->id)); > $assigninstance = new assign($cm->context, $cm, $course2); > $grade = $assigninstance->get_user_grade($student4->id, true); > $grade->grade = 40; > $assigninstance->update_grade($grade); > > $manuaitem->update_final_grade($student1->id, 1); > $manuaitem->update_final_grade($student3->id, 2); > > // Trigger a regrade. > grade_force_full_regrading($course1->id); > grade_force_full_regrading($course2->id); > grade_regrade_final_grades($course1->id); > grade_regrade_final_grades($course2->id); > > // Initialise reports. > $context1 = \context_course::instance($course1->id); > $context2 = \context_course::instance($course2->id); > > $gpr1 = new grade_plugin_return( > [ > 'type' => 'report', > 'plugin' => 'summary', > 'course' => $course1, > ] > ); > > $gpr2 = new grade_plugin_return( > [ > 'type' => 'report', > 'plugin' => 'summary', > 'course' => $course2, > ] > ); > > $report1 = new grade_report_summary($course1->id, $gpr1, $context1); > $report2 = new grade_report_summary($course2->id, $gpr2, $context2); > > $ungradedcounts = []; > $ungradedcounts[$course1->id] = $report1->ungraded_counts(); > $ungradedcounts[$course2->id] = $report2->ungraded_counts(); > > foreach ($ungradedcounts as $key => $ungradedcount) { > $gradeitems = grade_item::fetch_all(['courseid' => $key]); > if ($key == $course1->id) { > $gradeitemkeys = array_keys($gradeitems); > $ungradedcountskeys = array_keys($ungradedcount['ungradedcounts']); > > // For each grade item there is some student that is not graded yet in course 1. > $this->assertEmpty(array_diff_key($gradeitemkeys, $ungradedcountskeys)); > > // Only quiz does not have any grades, the remaning 4 grade items should have some. > // We can do more and match by gradeitem id numbers. But feels like overengeneering. > $this->assertEquals(4, count($ungradedcount['sumarray'])); > } else { > > // In course 2 there is one student, and he is graded. > $this->assertEmpty($ungradedcount['ungradedcounts']); > > // There are 2 grade items and they both have some grades. > $this->assertEquals(2, count($ungradedcount['sumarray'])); > } > > foreach ($gradeitems as $gradeitem) { > $sumgrades = null; > if (array_key_exists($gradeitem->id, $ungradedcount['ungradedcounts'])) { > $ungradeditem = $ungradedcount['ungradedcounts'][$gradeitem->id]; > if ($gradeitem->itemtype === 'course') { > $this->assertEquals(1, $ungradeditem->count); > } else if ($gradeitem->itemmodule === 'assign') { > $this->assertEquals(2, $ungradeditem->count); > } else if ($gradeitem->itemmodule === 'quiz') { > $this->assertEquals(3, $ungradeditem->count); > } else if ($gradeitem->itemtype === 'manual') { > $this->assertEquals(1, $ungradeditem->count); > } > } > > if (array_key_exists($gradeitem->id, $ungradedcount['sumarray'])) { > $sumgrades = $ungradedcount['sumarray'][$gradeitem->id]; > if ($gradeitem->itemtype === 'course') { > if ($key == $course1->id) { > $this->assertEquals('98.00000', $sumgrades); // 40 + 55 + 1 + 2 > } else { > $this->assertEquals('40.00000', $sumgrades); > } > } else if ($gradeitem->itemmodule === 'assign') { > if (($gradeitem->itemname === $assign1->name) || ($gradeitem->itemname === $assign3->name)) { > $this->assertEquals('40.00000', $sumgrades); > } else { > $this->assertEquals('55.00000', $sumgrades); > } > } else if ($gradeitem->itemtype === 'manual') { > $this->assertEquals('3.00000', $sumgrades); > } > } > } > } > } > > /** > * Tests that ungraded_counts calculates count and sum of grades correctly for groups when there are graded users. > * > * @covers \grade_report::ungraded_counts > */ > public function test_ungraded_count_sumgrades_groups() { > global $DB; > > $this->resetAfterTest(true); > > $course = $this->getDataGenerator()->create_course(); > > $studentrole = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST); > > // Create users. > > $student1 = $this->getDataGenerator()->create_user(['username' => 'student1']); > $student2 = $this->getDataGenerator()->create_user(['username' => 'student2']); > $student3 = $this->getDataGenerator()->create_user(['username' => 'student3']); > > // Enrol students. > $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id); > $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id); > $this->getDataGenerator()->enrol_user($student3->id, $course->id, $studentrole->id); > > $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); > $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); > $this->getDataGenerator()->create_group_member(['userid' => $student1->id, 'groupid' => $group1->id]); > $this->getDataGenerator()->create_group_member(['userid' => $student2->id, 'groupid' => $group2->id]); > $this->getDataGenerator()->create_group_member(['userid' => $student3->id, 'groupid' => $group2->id]); > $DB->set_field('course', 'groupmode', SEPARATEGROUPS, ['id' => $course->id]); > > // Create grade items in course 1. > $assign1 = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]); > $assign2 = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]); > $quiz1 = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]); > > $manuaitem = new \grade_item($this->getDataGenerator()->create_grade_item([ > 'itemname' => 'Grade item1', > 'idnumber' => 'git1', > 'courseid' => $course->id, > ])); > > // Grade users in first course. > $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign1->id)); > $assigninstance = new assign($cm->context, $cm, $course); > $grade = $assigninstance->get_user_grade($student1->id, true); > $grade->grade = 40; > $assigninstance->update_grade($grade); > > $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign2->id)); > $assigninstance = new assign($cm->context, $cm, $course); > $grade = $assigninstance->get_user_grade($student3->id, true); > $grade->grade = 50; > $assigninstance->update_grade($grade); > > $manuaitem->update_final_grade($student1->id, 1); > $manuaitem->update_final_grade($student3->id, 2); > > // Trigger a regrade. > grade_force_full_regrading($course->id); > grade_regrade_final_grades($course->id); > > // Initialise report. > $context = \context_course::instance($course->id); > > $gpr1 = new grade_plugin_return( > [ > 'type' => 'report', > 'plugin' => 'summary', > 'course' => $course, > 'groupid' => $group1->id, > ] > ); > > $gpr2 = new grade_plugin_return( > [ > 'type' => 'report', > 'plugin' => 'summary', > 'course' => $course, > 'groupid' => $group2->id, > ] > ); > > $report1 = new grade_report_summary($course->id, $gpr1, $context); > $report2 = new grade_report_summary($course->id, $gpr2, $context); > > $ungradedcounts = []; > $ungradedcounts[$group1->id] = $report1->ungraded_counts(); > $ungradedcounts[$group2->id] = $report2->ungraded_counts(); > > $gradeitems = grade_item::fetch_all(['courseid' => $course->id]); > > // In group1 there is 1 student and assign1 and quiz1 are not graded for him. > $this->assertEquals(2, count($ungradedcounts[$group1->id]['ungradedcounts'])); > > // In group1 manual grade item, assign1 and course total have some grades. > $this->assertEquals(3, count($ungradedcounts[$group1->id]['sumarray'])); > > // In group2 student2 has no grades at all so all 5 grade items should present. > $this->assertEquals(5, count($ungradedcounts[$group2->id]['ungradedcounts'])); > > // In group2 manual grade item, assign2 and course total have some grades. > $this->assertEquals(3, count($ungradedcounts[$group2->id]['sumarray'])); > > foreach ($gradeitems as $gradeitem) { > $sumgrades = null; > > foreach ($ungradedcounts as $key => $ungradedcount) { > if (array_key_exists($gradeitem->id, $ungradedcount['ungradedcounts'])) { > $ungradeditem = $ungradedcount['ungradedcounts'][$gradeitem->id]; > if ($key == $group1->id) { > // Both assign2 and quiz1 are not graded for student1. > $this->assertEquals(1, $ungradeditem->count); > } else { > if ($gradeitem->itemtype === 'course') { > $this->assertEquals(1, $ungradeditem->count); > } else if ($gradeitem->itemmodule === 'assign') { > if ($gradeitem->itemname === $assign1->name) { > // In group2 assign1 is not graded for anyone. > $this->assertEquals(2, $ungradeditem->count);} else {< $this->assertTrue(grade_tree::can_output_item($grandchild));> // In group2 assign2 is graded for student3. > $this->assertEquals(1, $ungradeditem->count); > } > } else if ($gradeitem->itemmodule === 'quiz') { > $this->assertEquals(2, $ungradeditem->count); > } else if ($gradeitem->itemtype === 'manual') { > $this->assertEquals(1, $ungradeditem->count); > } > } > } > > if (array_key_exists($gradeitem->id, $ungradedcount['sumarray'])) { > $sumgrades = $ungradedcount['sumarray'][$gradeitem->id]; > if ($key == $group1->id) { > if ($gradeitem->itemtype === 'course') { > $this->assertEquals('41.00000', $sumgrades); > } else if ($gradeitem->itemmodule === 'assign') { > $this->assertEquals('40.00000', $sumgrades); > } else if ($gradeitem->itemtype === 'manual') { > $this->assertEquals('1.00000', $sumgrades); > } > } else { > if ($gradeitem->itemtype === 'course') { > $this->assertEquals('52.00000', $sumgrades); > } else if ($gradeitem->itemmodule === 'assign') { > $this->assertEquals('50.00000', $sumgrades); > } else if ($gradeitem->itemtype === 'manual') { > $this->assertEquals('2.00000', $sumgrades); > } > } > } > } > } > } > > /** > * Tests for calculate_average. > * @dataProvider calculate_average_data() > * @param int $meanselection Whether to inlcude all grades or non-empty grades in aggregation. > * @param array $expectedmeancount expected meancount value > * @param array $expectedaverage expceted average value > * > * @covers \grade_report::calculate_average > */ > public function test_calculate_average(int $meanselection, array $expectedmeancount, array $expectedaverage) { > global $DB; > > $this->resetAfterTest(true); > > $course = $this->getDataGenerator()->create_course(); > > $student1 = $this->getDataGenerator()->create_user(['username' => 'student1']); > $student2 = $this->getDataGenerator()->create_user(['username' => 'student2']); > $student3 = $this->getDataGenerator()->create_user(['username' => 'student3']); > > $studentrole = $DB->get_record('role', ['shortname' => 'student'], '*', MUST_EXIST); > > // Enrol students. > $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id); > $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id); > $this->getDataGenerator()->enrol_user($student3->id, $course->id, $studentrole->id); > > // Create activities. > $assign1 = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]); > $assign2 = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]); > $quiz1 = $this->getDataGenerator()->create_module('quiz', ['course' => $course->id]); > > // Grade users. > $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign1->id)); > $assigninstance = new assign($cm->context, $cm, $course); > $grade = $assigninstance->get_user_grade($student1->id, true); > $grade->grade = 40; > $assigninstance->update_grade($grade); > > $grade = $assigninstance->get_user_grade($student2->id, true); > $grade->grade = 30; > $assigninstance->update_grade($grade); > > $cm = cm_info::create(get_coursemodule_from_instance('assign', $assign2->id)); > $assigninstance = new assign($cm->context, $cm, $course); > $grade = $assigninstance->get_user_grade($student3->id, true); > $grade->grade = 50; > $assigninstance->update_grade($grade); > > $grade = $assigninstance->get_user_grade($student1->id, true); > $grade->grade = 100; > $assigninstance->update_grade($grade); > > // Make a manual grade items. > $manuaitem = new \grade_item($this->getDataGenerator()->create_grade_item([ > 'itemname' => 'Grade item1', > 'idnumber' => 'git1', > 'courseid' => $course->id, > ])); > $manuaitem->update_final_grade($student1->id, 1); > $manuaitem->update_final_grade($student3->id, 2); > > // Initialise report. > $context = \context_course::instance($course->id); > > $gpr = new grade_plugin_return( > [ > 'type' => 'report', > 'plugin' => 'summary', > 'course' => $course, > ] > ); > > $report = new grade_report_summary($course->id, $gpr, $context); > > $ungradedcounts = $report->ungraded_counts(); > $ungradedcounts['report']['meanselection'] = $meanselection; > > $gradeitems = grade_item::fetch_all(['courseid' => $course->id]); > > foreach ($gradeitems as $gradeitem) { > $name = $gradeitem->itemname . ' ' . $gradeitem->itemtype; > $aggr = $report->calculate_average($gradeitem, $ungradedcounts); > > $this->assertEquals($expectedmeancount[$name], $aggr['meancount']); > $this->assertEquals($expectedaverage[$name], $aggr['average']);} }> } > /** } > * Data provider for test_calculate_average } > * } > * @return array of testing scenarios > */ > public function calculate_average_data() : array { > return [ > 'Non-empty grades' => [ > 'meanselection' => 1, > 'expectedmeancount' => [' course' => 3, 'Assignment 1 mod' => 2, 'Assignment 2 mod' => 2, > 'Quiz 1 mod' => 0, 'Grade item1 manual' => 2], > 'expectedaverage' => [' course' => 73.33333333333333, 'Assignment 1 mod' => 35.0, > 'Assignment 2 mod' => 75.0, 'Quiz 1 mod' => null, 'Grade item1 manual' => 1.5], > ], > 'All grades' => [ > 'meanselection' => 0, > 'expectedmeancount' => [' course' => 3, 'Assignment 1 mod' => 3, 'Assignment 2 mod' => 3, > 'Quiz 1 mod' => 3, 'Grade item1 manual' => 3], > 'expectedaverage' => [' course' => 73.33333333333333, 'Assignment 1 mod' => 23.333333333333332, > 'Assignment 2 mod' => 50.0, 'Quiz 1 mod' => null, 'Grade item1 manual' => 1.0], > ], > ];> > /** > * Tests for item types. > * > * @covers \grade_report::item_types > */ > public function test_item_types() { > $this->resetAfterTest(true); > > $course1 = $this->getDataGenerator()->create_course(); > $course2 = $this->getDataGenerator()->create_course(); > > // Create activities. > $this->getDataGenerator()->create_module('assign', ['course' => $course1->id]); > $this->getDataGenerator()->create_module('assign', ['course' => $course1->id]); > $this->getDataGenerator()->create_module('quiz', ['course' => $course1->id]); > > $this->getDataGenerator()->create_module('assign', ['course' => $course2->id]); > > // Create manual grade items. > new \grade_item($this->getDataGenerator()->create_grade_item([ > 'itemname' => 'Grade item1', > 'idnumber' => 'git1', > 'courseid' => $course1->id, > ])); > > new \grade_item($this->getDataGenerator()->create_grade_item([ > 'itemname' => 'Grade item2', > 'idnumber' => 'git2', > 'courseid' => $course2->id, > ])); > > // Create a grade category (it should not be fetched by item_types). > new \grade_category($this->getDataGenerator() > ->create_grade_category(['courseid' => $course1->id]), false); > > // Initialise reports. > $context = \context_course::instance($course1->id); > > $gpr = new grade_plugin_return( > [ > 'type' => 'report', > 'plugin' => 'summary', > 'course' => $course1, > ] > ); > > $report1 = new grade_report_summary($course1->id, $gpr, $context); > > $context = \context_course::instance($course2->id); > > $gpr = new grade_plugin_return( > [ > 'type' => 'report', > 'plugin' => 'summary', > 'course' => $course2, > ] > ); > > $report2 = new grade_report_summary($course2->id, $gpr, $context); > > $gradeitems1 = $report1->item_types(); > $gradeitems2 = $report2->item_types(); > > $this->assertEquals(3, count($gradeitems1)); > $this->assertEquals(2, count($gradeitems2)); > > $this->assertArrayHasKey('assign', $gradeitems1); > $this->assertArrayHasKey('quiz', $gradeitems1); > $this->assertArrayHasKey('manual', $gradeitems1); > > $this->assertArrayHasKey('assign', $gradeitems2); > $this->assertArrayHasKey('manual', $gradeitems2);> > /** > * Test get_gradable_users() function. > * > * @covers ::get_gradable_users > */ > public function test_get_gradable_users() { > global $DB; > > $this->setAdminUser(); > $this->resetAfterTest(true); > > $roleteacher = $DB->get_record('role', ['shortname' => 'teacher'], '*', MUST_EXIST); > > // Create a course. > $course = $this->getDataGenerator()->create_course(); > $coursecontext = \context_course::instance($course->id); > // Create groups. > $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); > $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]); > // Create and enrol a teacher and some students into the course. > $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher'); > $student1 = $this->getDataGenerator()->create_and_enrol($course, 'student'); > $student2 = $this->getDataGenerator()->create_and_enrol($course, 'student'); > $student3 = $this->getDataGenerator()->create_and_enrol($course, 'student'); > // Add student1 and student2 to group1. > $this->getDataGenerator()->create_group_member(['groupid' => $group1->id, 'userid' => $student1->id]); > $this->getDataGenerator()->create_group_member(['groupid' => $group1->id, 'userid' => $student2->id]); > // Add student3 to group2. > $this->getDataGenerator()->create_group_member(['groupid' => $group2->id, 'userid' => $student3->id]); > > // Perform a regrade before creating the report. > grade_regrade_final_grades($course->id); > // Should return all gradable users (only students). > $gradableusers = get_gradable_users($course->id); > $this->assertEqualsCanonicalizing([$student1->id, $student2->id, $student3->id], array_keys($gradableusers)); > > // Now, let's suspend the enrolment of student2. > $this->getDataGenerator()->enrol_user($student2->id, $course->id, 'student', 'manual', 0, 0, ENROL_USER_SUSPENDED); > // Should return only the active gradable users (student1 and student3). > $gradableusers = \grade_report::get_gradable_users($course->id); > $this->assertEqualsCanonicalizing([$student1->id, $student3->id], array_keys($gradableusers)); > > // Give teacher 'viewsuspendedusers' capability and set a preference to display suspended users. > assign_capability('moodle/course:viewsuspendedusers', CAP_ALLOW, $roleteacher->id, $coursecontext, true); > set_user_preference('grade_report_showonlyactiveenrol', false, $teacher); > accesslib_clear_all_caches_for_unit_testing(); > > $this->setUser($teacher); > // Should return all gradable users (including suspended enrolments). > $gradableusers = \grade_report::get_gradable_users($course->id); > $this->assertEqualsCanonicalizing([$student1->id, $student2->id, $student3->id], array_keys($gradableusers)); > > // Reactivate the course enrolment of student2. > $this->getDataGenerator()->enrol_user($student2->id, $course->id, 'student', 'manual', 0, 0, ENROL_USER_ACTIVE); > $this->setAdminUser(); > // Should return all gradable users from group1 (student1 and student2). > $gradableusers = \grade_report::get_gradable_users($course->id, $group1->id); > $this->assertEqualsCanonicalizing([$student1->id, $student2->id], array_keys($gradableusers)); > // Should return all gradable users from group2 (student3). > $gradableusers = \grade_report::get_gradable_users($course->id, $group2->id); > $this->assertEqualsCanonicalizing([$student3->id], array_keys($gradableusers));