4cf11157c2
Problem: In Moodle 4.2, an unintended change in behaviour occurred when locking and unlocking grade items. Previously, in Moodle 4.1, locking a grade item and then subsequently unlocking the grade item left specific grades for students still locked if they were being locked individually. However, in Moodle 4.2, the unintended change caused the individual grades to be unlocked along with the grade item. Solution: To address this issue, I modified the set_locked calls in action.php to pass the cascade parameter as false. Now, when locking or unlocking a grade item, only the grade item itself is affected, leaving individual grades unchanged. I have also modified the locking behaviour in the grade_category class. So, similarly, when locking or unlocking a grade category, the change applies only to the grade items and grade categories within the category, without expanding to individual grades. Explanation: By making this change, we ensure that the locking mechanism behaves as expected, providing a consistent and desirable user experience. Locking and unlocking a grade item or category will no longer inadvertently affect individual grades, preserving their locked status and avoiding loss of data when unlocking a grade item associated with the total mark of a category.
924 lines
46 KiB
PHP
924 lines
46 KiB
PHP
<?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/>.
|
|
|
|
namespace core;
|
|
|
|
defined('MOODLE_INTERNAL') || die();
|
|
|
|
require_once(__DIR__.'/fixtures/lib.php');
|
|
|
|
|
|
/**
|
|
* Test grade categories
|
|
*
|
|
* @package core
|
|
* @category test
|
|
* @copyright nicolas@moodle.com
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
class grade_category_test extends \grade_base_testcase {
|
|
|
|
public function test_grade_category() {
|
|
$this->sub_test_grade_category_construct();
|
|
$this->sub_test_grade_category_build_path();
|
|
$this->sub_test_grade_category_fetch();
|
|
$this->sub_test_grade_category_fetch_all();
|
|
$this->sub_test_grade_category_update();
|
|
$this->sub_test_grade_category_delete();
|
|
$this->sub_test_grade_category_insert();
|
|
$this->sub_test_grade_category_qualifies_for_regrading();
|
|
$this->sub_test_grade_category_force_regrading();
|
|
$this->sub_test_grade_category_aggregate_grades();
|
|
$this->sub_test_grade_category_apply_limit_rules();
|
|
$this->sub_test_grade_category_is_aggregationcoef_used();
|
|
$this->sub_test_grade_category_aggregation_uses_aggregationcoef();
|
|
$this->sub_test_grade_category_fetch_course_tree();
|
|
$this->sub_test_grade_category_get_children();
|
|
$this->sub_test_grade_category_load_grade_item();
|
|
$this->sub_test_grade_category_get_grade_item();
|
|
$this->sub_test_grade_category_load_parent_category();
|
|
$this->sub_test_grade_category_get_parent_category();
|
|
$this->sub_test_grade_category_get_name_escaped();
|
|
$this->sub_test_grade_category_get_name_unescaped();
|
|
$this->sub_test_grade_category_generate_grades_aggregationweight();
|
|
$this->sub_test_grade_category_set_parent();
|
|
$this->sub_test_grade_category_get_final();
|
|
$this->sub_test_grade_category_get_sortorder();
|
|
$this->sub_test_grade_category_set_sortorder();
|
|
$this->sub_test_grade_category_is_editable();
|
|
$this->sub_test_grade_category_move_after_sortorder();
|
|
$this->sub_test_grade_category_is_course_category();
|
|
$this->sub_test_grade_category_fetch_course_category();
|
|
$this->sub_test_grade_category_is_locked();
|
|
$this->sub_test_grade_category_set_locked();
|
|
$this->sub_test_grade_category_is_hidden();
|
|
$this->sub_test_grade_category_set_hidden();
|
|
$this->sub_test_grade_category_can_control_visibility();
|
|
$this->sub_test_grade_category_total_visibility();
|
|
|
|
// This won't work until MDL-11837 is complete.
|
|
// $this->sub_test_grade_category_generate_grades();
|
|
|
|
// Do this last as adding a second course category messes up the data.
|
|
$this->sub_test_grade_category_insert_course_category();
|
|
$this->sub_test_grade_category_is_extracredit_used();
|
|
$this->sub_test_grade_category_aggregation_uses_extracredit();
|
|
}
|
|
|
|
// Adds 3 new grade categories at various depths.
|
|
protected function sub_test_grade_category_construct() {
|
|
$course_category = \grade_category::fetch_course_category($this->courseid);
|
|
|
|
$params = new \stdClass();
|
|
|
|
$params->courseid = $this->courseid;
|
|
$params->fullname = 'unittestcategory4';
|
|
|
|
$grade_category = new \grade_category($params, false);
|
|
$grade_category->insert();
|
|
$this->grade_categories[] = $grade_category;
|
|
|
|
$this->assertEquals($params->courseid, $grade_category->courseid);
|
|
$this->assertEquals($params->fullname, $grade_category->fullname);
|
|
$this->assertEquals(2, $grade_category->depth);
|
|
$this->assertEquals("/$course_category->id/$grade_category->id/", $grade_category->path);
|
|
$parentpath = $grade_category->path;
|
|
|
|
// Test a child category.
|
|
$params->parent = $grade_category->id;
|
|
$params->fullname = 'unittestcategory5';
|
|
$grade_category = new \grade_category($params, false);
|
|
$grade_category->insert();
|
|
$this->grade_categories[] = $grade_category;
|
|
|
|
$this->assertEquals(3, $grade_category->depth);
|
|
$this->assertEquals($parentpath.$grade_category->id."/", $grade_category->path);
|
|
$parentpath = $grade_category->path;
|
|
|
|
// Test a third depth category.
|
|
$params->parent = $grade_category->id;
|
|
$params->fullname = 'unittestcategory6';
|
|
$grade_category = new \grade_category($params, false);
|
|
$grade_category->insert();
|
|
$this->grade_categories[50] = $grade_category;// Going to delete this one later hence the special index.
|
|
|
|
$this->assertEquals(4, $grade_category->depth);
|
|
$this->assertEquals($parentpath.$grade_category->id."/", $grade_category->path);
|
|
}
|
|
|
|
protected function sub_test_grade_category_build_path() {
|
|
$grade_category = new \grade_category($this->grade_categories[1]);
|
|
$this->assertTrue(method_exists($grade_category, 'build_path'));
|
|
$path = \grade_category::build_path($grade_category);
|
|
$this->assertEquals($grade_category->path, $path);
|
|
}
|
|
|
|
protected function sub_test_grade_category_fetch() {
|
|
$grade_category = new \grade_category();
|
|
$this->assertTrue(method_exists($grade_category, 'fetch'));
|
|
|
|
$grade_category = \grade_category::fetch(array('id'=>$this->grade_categories[0]->id));
|
|
$this->assertEquals($this->grade_categories[0]->id, $grade_category->id);
|
|
$this->assertEquals($this->grade_categories[0]->fullname, $grade_category->fullname);
|
|
}
|
|
|
|
protected function sub_test_grade_category_fetch_all() {
|
|
$grade_category = new \grade_category();
|
|
$this->assertTrue(method_exists($grade_category, 'fetch_all'));
|
|
|
|
$grade_categories = \grade_category::fetch_all(array('courseid'=>$this->courseid));
|
|
$this->assertEquals(count($this->grade_categories), count($grade_categories)-1);
|
|
}
|
|
|
|
protected function sub_test_grade_category_update() {
|
|
global $DB;
|
|
$grade_category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($grade_category, 'update'));
|
|
|
|
$grade_category->fullname = 'Updated info for this unittest grade_category';
|
|
$grade_category->path = null; // Path must be recalculated if missing.
|
|
$grade_category->depth = null;
|
|
$grade_category->aggregation = GRADE_AGGREGATE_MAX; // Should force regrading.
|
|
|
|
$grade_item = $grade_category->get_grade_item();
|
|
$this->assertEquals(0, $grade_item->needsupdate);
|
|
|
|
$this->assertTrue($grade_category->update());
|
|
|
|
$fullname = $DB->get_field('grade_categories', 'fullname', array('id' => $this->grade_categories[0]->id));
|
|
$this->assertEquals($grade_category->fullname, $fullname);
|
|
|
|
$path = $DB->get_field('grade_categories', 'path', array('id' => $this->grade_categories[0]->id));
|
|
$this->assertEquals($grade_category->path, $path);
|
|
|
|
$depth = $DB->get_field('grade_categories', 'depth', array('id' => $this->grade_categories[0]->id));
|
|
$this->assertEquals($grade_category->depth, $depth);
|
|
|
|
$grade_item = $grade_category->get_grade_item();
|
|
$this->assertEquals(1, $grade_item->needsupdate);
|
|
}
|
|
|
|
protected function sub_test_grade_category_delete() {
|
|
global $DB;
|
|
|
|
$grade_category = new \grade_category($this->grade_categories[50]);
|
|
$this->assertTrue(method_exists($grade_category, 'delete'));
|
|
|
|
$this->assertTrue($grade_category->delete());
|
|
$this->assertFalse($DB->get_record('grade_categories', array('id' => $grade_category->id)));
|
|
}
|
|
|
|
protected function sub_test_grade_category_insert() {
|
|
$course_category = \grade_category::fetch_course_category($this->courseid);
|
|
|
|
$grade_category = new \grade_category();
|
|
$this->assertTrue(method_exists($grade_category, 'insert'));
|
|
|
|
$grade_category->fullname = 'unittestcategory4';
|
|
$grade_category->courseid = $this->courseid;
|
|
$grade_category->aggregation = GRADE_AGGREGATE_MEAN;
|
|
$grade_category->aggregateonlygraded = 1;
|
|
$grade_category->keephigh = 100;
|
|
$grade_category->droplow = 10;
|
|
$grade_category->hidden = 0;
|
|
$grade_category->parent = $this->grade_categories[1]->id; // sub_test_grade_category_delete() removed the category at 0.
|
|
|
|
$grade_category->insert();
|
|
|
|
$this->assertEquals('/'.$course_category->id.'/'.$this->grade_categories[1]->parent.'/'.$this->grade_categories[1]->id.'/'.$grade_category->id.'/', $grade_category->path);
|
|
$this->assertEquals(4, $grade_category->depth);
|
|
|
|
$last_grade_category = end($this->grade_categories);
|
|
|
|
$this->assertFalse(empty($grade_category->grade_item));
|
|
$this->assertEquals($grade_category->id, $grade_category->grade_item->iteminstance);
|
|
$this->assertEquals('category', $grade_category->grade_item->itemtype);
|
|
|
|
$this->assertEquals($grade_category->id, $last_grade_category->id + 1);
|
|
$this->assertFalse(empty($grade_category->timecreated));
|
|
$this->assertFalse(empty($grade_category->timemodified));
|
|
}
|
|
|
|
protected function sub_test_grade_category_qualifies_for_regrading() {
|
|
$grade_category = new \grade_category($this->grade_categories[1]);
|
|
$this->assertTrue(method_exists($grade_category, 'qualifies_for_regrading'));
|
|
$this->assertFalse($grade_category->qualifies_for_regrading());
|
|
|
|
$grade_category->aggregation = GRADE_AGGREGATE_MAX;
|
|
$this->assertTrue($grade_category->qualifies_for_regrading());
|
|
|
|
$grade_category = new \grade_category($this->grade_categories[1]);
|
|
$grade_category->droplow = 99;
|
|
$this->assertTrue($grade_category->qualifies_for_regrading());
|
|
|
|
$grade_category = new \grade_category($this->grade_categories[1]);
|
|
$grade_category->keephigh = 99;
|
|
$this->assertTrue($grade_category->qualifies_for_regrading());
|
|
}
|
|
|
|
protected function sub_test_grade_category_force_regrading() {
|
|
$grade_category = new \grade_category($this->grade_categories[1]);
|
|
$this->assertTrue(method_exists($grade_category, 'force_regrading'));
|
|
|
|
$grade_category->load_grade_item();
|
|
$this->assertEquals(0, $grade_category->grade_item->needsupdate);
|
|
|
|
$grade_category->force_regrading();
|
|
|
|
$grade_category->grade_item = null;
|
|
$grade_category->load_grade_item();
|
|
|
|
$this->assertEquals(1, $grade_category->grade_item->needsupdate);
|
|
}
|
|
|
|
/**
|
|
* Tests the setting of the grade_grades aggregationweight column.
|
|
* Currently, this is only a regression test for MDL-51715.
|
|
* This must be run before sub_test_grade_category_set_parent(), which alters
|
|
* the fixture.
|
|
*/
|
|
protected function sub_test_grade_category_generate_grades_aggregationweight() {
|
|
global $DB;
|
|
|
|
// Start of regression test for MDL-51715.
|
|
// grade_categories [1] and [2] are child categories of [0]
|
|
// Ensure that grades have been generated with fixture data.
|
|
$childcat1 = new \grade_category($this->grade_categories[1]);
|
|
$childcat1itemid = $childcat1->load_grade_item()->id;
|
|
$childcat1->generate_grades();
|
|
$childcat2 = new \grade_category($this->grade_categories[2]);
|
|
$childcat2itemid = $childcat2->load_grade_item()->id;
|
|
$childcat2->generate_grades();
|
|
$parentcat = new \grade_category($this->grade_categories[0]);
|
|
$parentcat->generate_grades();
|
|
|
|
// Drop low and and re-generate to produce 'dropped' aggregation status.
|
|
$parentcat->droplow = 1;
|
|
$parentcat->generate_grades();
|
|
|
|
$this->assertTrue($DB->record_exists_select(
|
|
'grade_grades',
|
|
"aggregationstatus='dropped' and itemid in (?,?)",
|
|
array($childcat1itemid, $childcat2itemid)));
|
|
$this->assertFalse($DB->record_exists_select(
|
|
'grade_grades',
|
|
"aggregationstatus='dropped' and aggregationweight > 0.00"),
|
|
"aggregationweight should be 0.00 if aggregationstatus=='dropped'");
|
|
|
|
// Reset grade data to be consistent with fixture data.
|
|
$parentcat->droplow = 0;
|
|
$parentcat->generate_grades();
|
|
|
|
// Blank out the final grade for one of the child categories and re-generate
|
|
// to produce 'novalue' aggregationstatus. Direct DB update is testing shortcut.
|
|
$DB->set_field('grade_grades', 'finalgrade', null, array('itemid'=>$childcat1itemid));
|
|
$parentcat->generate_grades();
|
|
|
|
$this->assertFalse($DB->record_exists_select(
|
|
'grade_grades',
|
|
"aggregationstatus='dropped' and itemid in (?,?)",
|
|
array($childcat1itemid, $childcat2itemid)));
|
|
$this->assertTrue($DB->record_exists_select(
|
|
'grade_grades',
|
|
"aggregationstatus='novalue' and itemid = ?",
|
|
array($childcat1itemid)));
|
|
$this->assertFalse($DB->record_exists_select(
|
|
'grade_grades',
|
|
"aggregationstatus='novalue' and aggregationweight > 0.00"),
|
|
"aggregationweight should be 0.00 if aggregationstatus=='novalue'");
|
|
|
|
// Re-generate to be consistent with fixture data.
|
|
$childcat1->generate_grades();
|
|
$parentcat->generate_grades();
|
|
// End of regression test for MDL-51715.
|
|
}
|
|
|
|
/**
|
|
* Tests the calculation of grades using the various aggregation methods with and without hidden grades
|
|
* This will not work entirely until MDL-11837 is done
|
|
*/
|
|
protected function sub_test_grade_category_generate_grades() {
|
|
global $DB;
|
|
|
|
// Inserting some special grade items to make testing the final grade calculation easier.
|
|
$params = new \stdClass();
|
|
$params->courseid = $this->courseid;
|
|
$params->fullname = 'unittestgradecalccategory';
|
|
$params->aggregation = GRADE_AGGREGATE_MEAN;
|
|
$params->aggregateonlygraded = 0;
|
|
$grade_category = new \grade_category($params, false);
|
|
$grade_category->insert();
|
|
|
|
$this->assertTrue(method_exists($grade_category, 'generate_grades'));
|
|
|
|
$grade_category->load_grade_item();
|
|
$cgi = $grade_category->get_grade_item();
|
|
$cgi->grademin = 0;
|
|
$cgi->grademax = 20; // 3 grade items out of 10 but category is out of 20 to force scaling to occur.
|
|
$cgi->update();
|
|
|
|
// 3 grade items each with a maximum grade of 10.
|
|
$grade_items = array();
|
|
for ($i=0; $i<3; $i++) {
|
|
$grade_items[$i] = new \grade_item();
|
|
$grade_items[$i]->courseid = $this->courseid;
|
|
$grade_items[$i]->categoryid = $grade_category->id;
|
|
$grade_items[$i]->itemname = 'manual grade_item '.$i;
|
|
$grade_items[$i]->itemtype = 'manual';
|
|
$grade_items[$i]->itemnumber = 0;
|
|
$grade_items[$i]->needsupdate = false;
|
|
$grade_items[$i]->gradetype = GRADE_TYPE_VALUE;
|
|
$grade_items[$i]->grademin = 0;
|
|
$grade_items[$i]->grademax = 10;
|
|
$grade_items[$i]->iteminfo = 'Manual grade item used for unit testing';
|
|
$grade_items[$i]->timecreated = time();
|
|
$grade_items[$i]->timemodified = time();
|
|
|
|
// Used as the weight by weighted mean and as extra credit by mean with extra credit.
|
|
// Will be 0, 1 and 2.
|
|
$grade_items[$i]->aggregationcoef = $i;
|
|
|
|
$grade_items[$i]->insert();
|
|
}
|
|
|
|
// A grade for each grade item.
|
|
$grade_grades = array();
|
|
for ($i=0; $i<3; $i++) {
|
|
$grade_grades[$i] = new \grade_grade();
|
|
$grade_grades[$i]->itemid = $grade_items[$i]->id;
|
|
$grade_grades[$i]->userid = $this->userid;
|
|
$grade_grades[$i]->rawgrade = ($i+1)*2; // Produce grade grades of 2, 4 and 6.
|
|
$grade_grades[$i]->finalgrade = ($i+1)*2;
|
|
$grade_grades[$i]->timecreated = time();
|
|
$grade_grades[$i]->timemodified = time();
|
|
$grade_grades[$i]->information = '1 of 2 grade_grades';
|
|
$grade_grades[$i]->informationformat = FORMAT_PLAIN;
|
|
$grade_grades[$i]->feedback = 'Good, but not good enough..';
|
|
$grade_grades[$i]->feedbackformat = FORMAT_PLAIN;
|
|
|
|
$grade_grades[$i]->insert();
|
|
}
|
|
|
|
// 3 grade items with 1 grade_grade each.
|
|
// grade grades have the values 2, 4 and 6.
|
|
|
|
// First correct answer is the aggregate with all 3 grades.
|
|
// Second correct answer is with the first grade (value 2) hidden.
|
|
|
|
$this->helper_test_grade_agg_method($grade_category, $grade_items, $grade_grades, GRADE_AGGREGATE_MEDIAN, 'GRADE_AGGREGATE_MEDIAN', 8, 8);
|
|
$this->helper_test_grade_agg_method($grade_category, $grade_items, $grade_grades, GRADE_AGGREGATE_MAX, 'GRADE_AGGREGATE_MAX', 12, 12);
|
|
$this->helper_test_grade_agg_method($grade_category, $grade_items, $grade_grades, GRADE_AGGREGATE_MODE, 'GRADE_AGGREGATE_MODE', 12, 12);
|
|
|
|
// Weighted mean. note grade totals are rounded to an int to prevent rounding discrepancies. correct final grade isnt actually exactly 10
|
|
// 3 items with grades 2, 4 and 6 with weights 0, 1 and 2 and all out of 10. then doubled to be out of 20.
|
|
$this->helper_test_grade_agg_method($grade_category, $grade_items, $grade_grades, GRADE_AGGREGATE_WEIGHTED_MEAN, 'GRADE_AGGREGATE_WEIGHTED_MEAN', 10, 10);
|
|
|
|
// Simple weighted mean.
|
|
// 3 items with grades 2, 4 and 6 equally weighted and all out of 10. then doubled to be out of 20.
|
|
$this->helper_test_grade_agg_method($grade_category, $grade_items, $grade_grades, GRADE_AGGREGATE_WEIGHTED_MEAN2, 'GRADE_AGGREGATE_WEIGHTED_MEAN2', 8, 10);
|
|
|
|
// Mean of grades with extra credit.
|
|
// 3 items with grades 2, 4 and 6 with extra credit 0, 1 and 2 equally weighted and all out of 10. then doubled to be out of 20.
|
|
$this->helper_test_grade_agg_method($grade_category, $grade_items, $grade_grades, GRADE_AGGREGATE_EXTRACREDIT_MEAN, 'GRADE_AGGREGATE_EXTRACREDIT_MEAN', 10, 13);
|
|
|
|
// Aggregation tests the are affected by a hidden grade currently dont work as we dont store the altered grade in the database
|
|
// instead an in memory recalculation is done. This should be remedied by MDL-11837.
|
|
|
|
// Fails with 1 grade hidden. still reports 8 as being correct.
|
|
$this->helper_test_grade_agg_method($grade_category, $grade_items, $grade_grades, GRADE_AGGREGATE_MEAN, 'GRADE_AGGREGATE_MEAN', 8, 10);
|
|
|
|
// Fails with 1 grade hidden. still reports 4 as being correct.
|
|
$this->helper_test_grade_agg_method($grade_category, $grade_items, $grade_grades, GRADE_AGGREGATE_MIN, 'GRADE_AGGREGATE_MIN', 4, 8);
|
|
|
|
// Fails with 1 grade hidden. still reports 12 as being correct.
|
|
$this->helper_test_grade_agg_method($grade_category, $grade_items, $grade_grades, GRADE_AGGREGATE_SUM, 'GRADE_AGGREGATE_SUM', 12, 10);
|
|
}
|
|
|
|
/**
|
|
* Test grade category aggregation using the supplied grade objects and aggregation method
|
|
* @param \grade_category $grade_category the category to be tested
|
|
* @param array $grade_items array of instance of grade_item
|
|
* @param array $grade_grades array of instances of grade_grade
|
|
* @param int $aggmethod the aggregation method to apply ie GRADE_AGGREGATE_MEAN
|
|
* @param string $aggmethodname the name of the aggregation method to apply. Used to display any test failure messages
|
|
* @param int $correct1 the correct final grade for the category with NO items hidden
|
|
* @param int $correct2 the correct final grade for the category with the grade at $grade_grades[0] hidden
|
|
* @return void
|
|
*/
|
|
protected function helper_test_grade_agg_method($grade_category, $grade_items, $grade_grades, $aggmethod, $aggmethodname, $correct1, $correct2) {
|
|
$grade_category->aggregation = $aggmethod;
|
|
$grade_category->update();
|
|
|
|
// Check grade_item isnt hidden from a previous test.
|
|
$grade_items[0]->set_hidden(0, true);
|
|
$this->helper_test_grade_aggregation_result($grade_category, $correct1, 'Testing aggregation method('.$aggmethodname.') with no items hidden %s');
|
|
|
|
// Hide the grade item with grade of 2.
|
|
$grade_items[0]->set_hidden(1, true);
|
|
$this->helper_test_grade_aggregation_result($grade_category, $correct2, 'Testing aggregation method('.$aggmethodname.') with 1 item hidden %s');
|
|
}
|
|
|
|
/**
|
|
* Verify the value of the category grade item for $this->userid
|
|
* @param \grade_category $grade_category the category to be tested
|
|
* @param int $correctgrade the expected grade
|
|
* @param string $msg The message that should be displayed if the correct grade is not found
|
|
* @return void
|
|
*/
|
|
protected function helper_test_grade_aggregation_result($grade_category, $correctgrade, $msg) {
|
|
global $DB;
|
|
|
|
$category_grade_item = $grade_category->get_grade_item();
|
|
|
|
// This creates all the grade_grades we need.
|
|
grade_regrade_final_grades($this->courseid);
|
|
|
|
$grade = $DB->get_record('grade_grades', array('itemid'=>$category_grade_item->id, 'userid'=>$this->userid));
|
|
$this->assertWithinMargin($grade->rawgrade, $grade->rawgrademin, $grade->rawgrademax);
|
|
$this->assertEquals(intval($correctgrade), intval($grade->finalgrade), $msg);
|
|
|
|
/*
|
|
* TODO this doesnt work as the grade_grades created by $grade_category->generate_grades(); dont
|
|
* observe the category's max grade
|
|
// delete the grade_grades for the category itself and check they get recreated correctly.
|
|
$DB->delete_records('grade_grades', array('itemid'=>$category_grade_item->id));
|
|
$grade_category->generate_grades();
|
|
|
|
$grade = $DB->get_record('grade_grades', array('itemid'=>$category_grade_item->id, 'userid'=>$this->userid));
|
|
$this->assertWithinMargin($grade->rawgrade, $grade->rawgrademin, $grade->rawgrademax);
|
|
$this->assertEquals(intval($correctgrade), intval($grade->finalgrade), $msg);
|
|
*
|
|
*/
|
|
}
|
|
|
|
protected function sub_test_grade_category_aggregate_grades() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'aggregate_grades'));
|
|
// Tested more fully via test_grade_category_generate_grades().
|
|
}
|
|
|
|
protected function sub_test_grade_category_apply_limit_rules() {
|
|
$items[$this->grade_items[0]->id] = new \grade_item($this->grade_items[0], false);
|
|
$items[$this->grade_items[1]->id] = new \grade_item($this->grade_items[1], false);
|
|
$items[$this->grade_items[2]->id] = new \grade_item($this->grade_items[2], false);
|
|
$items[$this->grade_items[4]->id] = new \grade_item($this->grade_items[4], false);
|
|
|
|
// Test excluding the lowest 2 out of 4 grades from aggregation with no 0 grades.
|
|
$category = new \grade_category();
|
|
$category->droplow = 2;
|
|
$grades = array($this->grade_items[0]->id=>5.374,
|
|
$this->grade_items[1]->id=>9.4743,
|
|
$this->grade_items[2]->id=>2.5474,
|
|
$this->grade_items[4]->id=>7.3754);
|
|
$category->apply_limit_rules($grades, $items);
|
|
$this->assertEquals(count($grades), 2);
|
|
$this->assertEquals($grades[$this->grade_items[1]->id], 9.4743);
|
|
$this->assertEquals($grades[$this->grade_items[4]->id], 7.3754);
|
|
|
|
// Test aggregating only the highest 1 out of 4 grades.
|
|
$category = new \grade_category();
|
|
$category->keephigh = 1;
|
|
$category->droplow = 0;
|
|
$grades = array($this->grade_items[0]->id=>5.374,
|
|
$this->grade_items[1]->id=>9.4743,
|
|
$this->grade_items[2]->id=>2.5474,
|
|
$this->grade_items[4]->id=>7.3754);
|
|
$category->apply_limit_rules($grades, $items);
|
|
$this->assertEquals(count($grades), 1);
|
|
$grade = reset($grades);
|
|
$this->assertEquals(9.4743, $grade);
|
|
|
|
// Test excluding the lowest 2 out of 4 grades from aggregation with no 0 grades.
|
|
// An extra credit grade item should be kept even if droplow means it would otherwise be excluded.
|
|
$category = new \grade_category();
|
|
$category->droplow = 2;
|
|
$category->aggregation = GRADE_AGGREGATE_SUM;
|
|
$items[$this->grade_items[2]->id]->aggregationcoef = 1; // Mark grade item 2 as "extra credit".
|
|
$grades = array($this->grade_items[0]->id=>5.374,
|
|
$this->grade_items[1]->id=>9.4743,
|
|
$this->grade_items[2]->id=>2.5474,
|
|
$this->grade_items[4]->id=>7.3754);
|
|
$category->apply_limit_rules($grades, $items);
|
|
$this->assertEquals(count($grades), 2);
|
|
$this->assertEquals($grades[$this->grade_items[1]->id], 9.4743);
|
|
$this->assertEquals($grades[$this->grade_items[2]->id], 2.5474);
|
|
|
|
// Test only aggregating the highest 1 out of 4 grades.
|
|
// An extra credit grade item is retained in addition to the highest grade.
|
|
$category = new \grade_category();
|
|
$category->keephigh = 1;
|
|
$category->droplow = 0;
|
|
$category->aggregation = GRADE_AGGREGATE_SUM;
|
|
$items[$this->grade_items[2]->id]->aggregationcoef = 1; // Mark grade item 2 as "extra credit".
|
|
$grades = array($this->grade_items[0]->id=>5.374,
|
|
$this->grade_items[1]->id=>9.4743,
|
|
$this->grade_items[2]->id=>2.5474,
|
|
$this->grade_items[4]->id=>7.3754);
|
|
$category->apply_limit_rules($grades, $items);
|
|
$this->assertEquals(count($grades), 2);
|
|
$this->assertEquals($grades[$this->grade_items[1]->id], 9.4743);
|
|
$this->assertEquals($grades[$this->grade_items[2]->id], 2.5474);
|
|
|
|
// Test excluding the lowest 1 out of 4 grades from aggregation with two 0 grades.
|
|
$items[$this->grade_items[2]->id]->aggregationcoef = 0; // Undo marking grade item 2 as "extra credit".
|
|
$category = new \grade_category();
|
|
$category->droplow = 1;
|
|
$category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2; // Simple weighted mean.
|
|
$grades = array($this->grade_items[0]->id=>0, // 0 out of 110. Should be excluded from aggregation.
|
|
$this->grade_items[1]->id=>5, // 5 out of 100.
|
|
$this->grade_items[2]->id=>2, // 0 out of 6.
|
|
$this->grade_items[4]->id=>0); // 0 out of 100.
|
|
$category->apply_limit_rules($grades, $items);
|
|
$this->assertEquals(count($grades), 3);
|
|
$this->assertEquals($grades[$this->grade_items[1]->id], 5);
|
|
$this->assertEquals($grades[$this->grade_items[2]->id], 2);
|
|
$this->assertEquals($grades[$this->grade_items[4]->id], 0);
|
|
|
|
// Test excluding the lowest 2 out of 4 grades from aggregation with three 0 grades.
|
|
$category = new \grade_category();
|
|
$category->droplow = 2;
|
|
$category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2; // Simple weighted mean.
|
|
$grades = array($this->grade_items[0]->id=>0, // 0 out of 110. Should be excluded from aggregation.
|
|
$this->grade_items[1]->id=>5, // 5 out of 100.
|
|
$this->grade_items[2]->id=>0, // 0 out of 6.
|
|
$this->grade_items[4]->id=>0); // 0 out of 100. Should be excluded from aggregation.
|
|
$category->apply_limit_rules($grades, $items);
|
|
$this->assertEquals(count($grades), 2);
|
|
$this->assertEquals($grades[$this->grade_items[1]->id], 5);
|
|
$this->assertEquals($grades[$this->grade_items[2]->id], 0);
|
|
|
|
// Test excluding the lowest 5 out of 4 grades from aggregation.
|
|
// Just to check we handle this sensibly.
|
|
$category = new \grade_category();
|
|
$category->droplow = 5;
|
|
$category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2; // Simple weighted mean.
|
|
$grades = array($this->grade_items[0]->id=>0, // 0 out of 110. Should be excluded from aggregation.
|
|
$this->grade_items[1]->id=>5, // 5 out of 100.
|
|
$this->grade_items[2]->id=>6, // 6 out of 6.
|
|
$this->grade_items[4]->id=>1);// 1 out of 100. Should be excluded from aggregation.
|
|
$category->apply_limit_rules($grades, $items);
|
|
$this->assertEquals(count($grades), 0);
|
|
|
|
// Test excluding the lowest 4 out of 4 grades from aggregation with one marked as extra credit.
|
|
$category = new \grade_category();
|
|
$category->droplow = 4;
|
|
$category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2; // Simple weighted mean.
|
|
$items[$this->grade_items[2]->id]->aggregationcoef = 1; // Mark grade item 2 as "extra credit".
|
|
$grades = array($this->grade_items[0]->id=>0, // 0 out of 110. Should be excluded from aggregation.
|
|
$this->grade_items[1]->id=>5, // 5 out of 100. Should be excluded from aggregation.
|
|
$this->grade_items[2]->id=>6, // 6 out of 6. Extra credit. Should be retained.
|
|
$this->grade_items[4]->id=>1);// 1 out of 100. Should be excluded from aggregation.
|
|
$category->apply_limit_rules($grades, $items);
|
|
$this->assertEquals(count($grades), 1);
|
|
$this->assertEquals($grades[$this->grade_items[2]->id], 6);
|
|
|
|
// MDL-35667 - There was an infinite loop if several items had the same grade and at least one was extra credit.
|
|
$category = new \grade_category();
|
|
$category->droplow = 1;
|
|
$category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2; // Simple weighted mean.
|
|
$items[$this->grade_items[1]->id]->aggregationcoef = 1; // Mark grade item 1 as "extra credit".
|
|
$grades = array($this->grade_items[0]->id=>1, // 1 out of 110. Should be excluded from aggregation.
|
|
$this->grade_items[1]->id=>1, // 1 out of 100. Extra credit. Should be retained.
|
|
$this->grade_items[2]->id=>1, // 1 out of 6. Should be retained.
|
|
$this->grade_items[4]->id=>1);// 1 out of 100. Should be retained.
|
|
$category->apply_limit_rules($grades, $items);
|
|
$this->assertEquals(count($grades), 3);
|
|
$this->assertEquals($grades[$this->grade_items[1]->id], 1);
|
|
$this->assertEquals($grades[$this->grade_items[2]->id], 1);
|
|
$this->assertEquals($grades[$this->grade_items[4]->id], 1);
|
|
|
|
}
|
|
|
|
protected function sub_test_grade_category_is_aggregationcoef_used() {
|
|
$category = new \grade_category();
|
|
// Following use aggregationcoef.
|
|
$category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN;
|
|
$this->assertTrue($category->is_aggregationcoef_used());
|
|
$category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2;
|
|
$this->assertTrue($category->is_aggregationcoef_used());
|
|
$category->aggregation = GRADE_AGGREGATE_EXTRACREDIT_MEAN;
|
|
$this->assertTrue($category->is_aggregationcoef_used());
|
|
$category->aggregation = GRADE_AGGREGATE_SUM;
|
|
$this->assertTrue($category->is_aggregationcoef_used());
|
|
|
|
// Following don't use aggregationcoef.
|
|
$category->aggregation = GRADE_AGGREGATE_MAX;
|
|
$this->assertFalse($category->is_aggregationcoef_used());
|
|
$category->aggregation = GRADE_AGGREGATE_MEAN;
|
|
$this->assertFalse($category->is_aggregationcoef_used());
|
|
$category->aggregation = GRADE_AGGREGATE_MEDIAN;
|
|
$this->assertFalse($category->is_aggregationcoef_used());
|
|
$category->aggregation = GRADE_AGGREGATE_MIN;
|
|
$this->assertFalse($category->is_aggregationcoef_used());
|
|
$category->aggregation = GRADE_AGGREGATE_MODE;
|
|
$this->assertFalse($category->is_aggregationcoef_used());
|
|
}
|
|
|
|
protected function sub_test_grade_category_aggregation_uses_aggregationcoef() {
|
|
|
|
$this->assertTrue(\grade_category::aggregation_uses_aggregationcoef(GRADE_AGGREGATE_WEIGHTED_MEAN));
|
|
$this->assertTrue(\grade_category::aggregation_uses_aggregationcoef(GRADE_AGGREGATE_WEIGHTED_MEAN2));
|
|
$this->assertTrue(\grade_category::aggregation_uses_aggregationcoef(GRADE_AGGREGATE_EXTRACREDIT_MEAN));
|
|
$this->assertTrue(\grade_category::aggregation_uses_aggregationcoef(GRADE_AGGREGATE_SUM));
|
|
|
|
$this->assertFalse(\grade_category::aggregation_uses_aggregationcoef(GRADE_AGGREGATE_MAX));
|
|
$this->assertFalse(\grade_category::aggregation_uses_aggregationcoef(GRADE_AGGREGATE_MEAN));
|
|
$this->assertFalse(\grade_category::aggregation_uses_aggregationcoef(GRADE_AGGREGATE_MEDIAN));
|
|
$this->assertFalse(\grade_category::aggregation_uses_aggregationcoef(GRADE_AGGREGATE_MIN));
|
|
$this->assertFalse(\grade_category::aggregation_uses_aggregationcoef(GRADE_AGGREGATE_MODE));
|
|
}
|
|
|
|
protected function sub_test_grade_category_fetch_course_tree() {
|
|
$category = new \grade_category();
|
|
$this->assertTrue(method_exists($category, 'fetch_course_tree'));
|
|
// TODO: add some tests.
|
|
}
|
|
|
|
protected function sub_test_grade_category_get_children() {
|
|
$course_category = \grade_category::fetch_course_category($this->courseid);
|
|
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'get_children'));
|
|
|
|
$children_array = $category->get_children(0);
|
|
|
|
$this->assertTrue(is_array($children_array));
|
|
$this->assertFalse(empty($children_array[2]));
|
|
$this->assertFalse(empty($children_array[2]['object']));
|
|
$this->assertFalse(empty($children_array[2]['children']));
|
|
$this->assertEquals($this->grade_categories[1]->id, $children_array[2]['object']->id);
|
|
$this->assertEquals($this->grade_categories[2]->id, $children_array[5]['object']->id);
|
|
$this->assertEquals($this->grade_items[0]->id, $children_array[2]['children'][3]['object']->id);
|
|
$this->assertEquals($this->grade_items[1]->id, $children_array[2]['children'][4]['object']->id);
|
|
$this->assertEquals($this->grade_items[2]->id, $children_array[5]['children'][6]['object']->id);
|
|
}
|
|
|
|
protected function sub_test_grade_category_load_grade_item() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'load_grade_item'));
|
|
$this->assertEquals(null, $category->grade_item);
|
|
$category->load_grade_item();
|
|
$this->assertEquals($this->grade_items[3]->id, $category->grade_item->id);
|
|
}
|
|
|
|
protected function sub_test_grade_category_get_grade_item() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'get_grade_item'));
|
|
$grade_item = $category->get_grade_item();
|
|
$this->assertEquals($this->grade_items[3]->id, $grade_item->id);
|
|
}
|
|
|
|
protected function sub_test_grade_category_load_parent_category() {
|
|
$category = new \grade_category($this->grade_categories[1]);
|
|
$this->assertTrue(method_exists($category, 'load_parent_category'));
|
|
$this->assertEquals(null, $category->parent_category);
|
|
$category->load_parent_category();
|
|
$this->assertEquals($this->grade_categories[0]->id, $category->parent_category->id);
|
|
}
|
|
|
|
protected function sub_test_grade_category_get_parent_category() {
|
|
$category = new \grade_category($this->grade_categories[1]);
|
|
$this->assertTrue(method_exists($category, 'get_parent_category'));
|
|
$parent_category = $category->get_parent_category();
|
|
$this->assertEquals($this->grade_categories[0]->id, $parent_category->id);
|
|
}
|
|
|
|
/**
|
|
* Tests the getter of the category fullname with escaped HTML.
|
|
*/
|
|
protected function sub_test_grade_category_get_name_escaped() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'get_name'));
|
|
$this->assertEquals(format_string($this->grade_categories[0]->fullname, true, ['escape' => true]),
|
|
$category->get_name(true));
|
|
}
|
|
|
|
/**
|
|
* Tests the getter of the category fullname with unescaped HTML.
|
|
*/
|
|
protected function sub_test_grade_category_get_name_unescaped() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'get_name'));
|
|
$this->assertEquals(format_string($this->grade_categories[0]->fullname, true, ['escape' => false]),
|
|
$category->get_name(false));
|
|
}
|
|
|
|
protected function sub_test_grade_category_set_parent() {
|
|
$category = new \grade_category($this->grade_categories[1]);
|
|
$this->assertTrue(method_exists($category, 'set_parent'));
|
|
// TODO: implement detailed tests.
|
|
|
|
$course_category = \grade_category::fetch_course_category($this->courseid);
|
|
$this->assertTrue($category->set_parent($course_category->id));
|
|
$this->assertEquals($course_category->id, $category->parent);
|
|
}
|
|
|
|
protected function sub_test_grade_category_get_final() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'get_final'));
|
|
$category->load_grade_item();
|
|
$this->assertEquals($category->get_final(), $category->grade_item->get_final());
|
|
}
|
|
|
|
protected function sub_test_grade_category_get_sortorder() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'get_sortorder'));
|
|
$category->load_grade_item();
|
|
$this->assertEquals($category->get_sortorder(), $category->grade_item->get_sortorder());
|
|
}
|
|
|
|
protected function sub_test_grade_category_set_sortorder() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'set_sortorder'));
|
|
$category->load_grade_item();
|
|
$this->assertEquals($category->set_sortorder(10), $category->grade_item->set_sortorder(10));
|
|
}
|
|
|
|
protected function sub_test_grade_category_move_after_sortorder() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'move_after_sortorder'));
|
|
$category->load_grade_item();
|
|
$this->assertEquals($category->move_after_sortorder(10), $category->grade_item->move_after_sortorder(10));
|
|
}
|
|
|
|
protected function sub_test_grade_category_is_course_category() {
|
|
$category = \grade_category::fetch_course_category($this->courseid);
|
|
$this->assertTrue(method_exists($category, 'is_course_category'));
|
|
$this->assertTrue($category->is_course_category());
|
|
}
|
|
|
|
protected function sub_test_grade_category_fetch_course_category() {
|
|
$category = new \grade_category();
|
|
$this->assertTrue(method_exists($category, 'fetch_course_category'));
|
|
$category = \grade_category::fetch_course_category($this->courseid);
|
|
$this->assertTrue(empty($category->parent));
|
|
}
|
|
/**
|
|
* TODO implement
|
|
*/
|
|
protected function sub_test_grade_category_is_editable() {
|
|
|
|
}
|
|
|
|
protected function sub_test_grade_category_is_locked() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'is_locked'));
|
|
$category->load_grade_item();
|
|
$this->assertEquals($category->is_locked(), $category->grade_item->is_locked());
|
|
}
|
|
|
|
protected function sub_test_grade_category_set_locked() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'set_locked'));
|
|
|
|
// Even though a grade that needs updating cannot be locked, set_locked will return true because it will successfully
|
|
// schedule the locking for as soon as final grades are recalculated.
|
|
$this->assertTrue($category->set_locked(1));
|
|
// The category should not be locked yet as we are waiting for a recalculation.
|
|
$this->assertFalse($category->is_locked());
|
|
grade_regrade_final_grades($this->courseid);
|
|
|
|
// Get the category from the db again.
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
// The category is locked now.
|
|
$this->assertTrue($category->is_locked());
|
|
}
|
|
|
|
protected function sub_test_grade_category_is_hidden() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'is_hidden'));
|
|
$category->load_grade_item();
|
|
$this->assertEquals($category->is_hidden(), $category->grade_item->is_hidden());
|
|
}
|
|
|
|
protected function sub_test_grade_category_set_hidden() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue(method_exists($category, 'set_hidden'));
|
|
$category->set_hidden(1, true);
|
|
$category->load_grade_item();
|
|
$this->assertEquals(true, $category->grade_item->is_hidden());
|
|
}
|
|
|
|
protected function sub_test_grade_category_can_control_visibility() {
|
|
$category = new \grade_category($this->grade_categories[0]);
|
|
$this->assertTrue($category->can_control_visibility());
|
|
}
|
|
|
|
protected function sub_test_grade_category_insert_course_category() {
|
|
// Beware: adding a duplicate course category messes up the data in a way that's hard to recover from.
|
|
$grade_category = new \grade_category();
|
|
$this->assertTrue(method_exists($grade_category, 'insert_course_category'));
|
|
|
|
$id = $grade_category->insert_course_category($this->courseid);
|
|
$this->assertNotNull($id);
|
|
$this->assertEquals('?', $grade_category->fullname);
|
|
$this->assertEquals(GRADE_AGGREGATE_WEIGHTED_MEAN2, $grade_category->aggregation);
|
|
$this->assertEquals("/$id/", $grade_category->path);
|
|
$this->assertEquals(1, $grade_category->depth);
|
|
$this->assertNull($grade_category->parent);
|
|
}
|
|
|
|
protected function generate_random_raw_grade($item, $userid) {
|
|
$grade = new \grade_grade();
|
|
$grade->itemid = $item->id;
|
|
$grade->userid = $userid;
|
|
$grade->grademin = 0;
|
|
$grade->grademax = 1;
|
|
$valuetype = "grade$item->gradetype";
|
|
$grade->rawgrade = rand(0, 1000) / 1000;
|
|
$grade->insert();
|
|
return $grade->rawgrade;
|
|
}
|
|
|
|
protected function sub_test_grade_category_is_extracredit_used() {
|
|
$category = new \grade_category();
|
|
// Following use aggregationcoef.
|
|
$category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN2;
|
|
$this->assertTrue($category->is_extracredit_used());
|
|
$category->aggregation = GRADE_AGGREGATE_EXTRACREDIT_MEAN;
|
|
$this->assertTrue($category->is_extracredit_used());
|
|
$category->aggregation = GRADE_AGGREGATE_SUM;
|
|
$this->assertTrue($category->is_extracredit_used());
|
|
|
|
// Following don't use aggregationcoef.
|
|
$category->aggregation = GRADE_AGGREGATE_WEIGHTED_MEAN;
|
|
$this->assertFalse($category->is_extracredit_used());
|
|
$category->aggregation = GRADE_AGGREGATE_MAX;
|
|
$this->assertFalse($category->is_extracredit_used());
|
|
$category->aggregation = GRADE_AGGREGATE_MEAN;
|
|
$this->assertFalse($category->is_extracredit_used());
|
|
$category->aggregation = GRADE_AGGREGATE_MEDIAN;
|
|
$this->assertFalse($category->is_extracredit_used());
|
|
$category->aggregation = GRADE_AGGREGATE_MIN;
|
|
$this->assertFalse($category->is_extracredit_used());
|
|
$category->aggregation = GRADE_AGGREGATE_MODE;
|
|
$this->assertFalse($category->is_extracredit_used());
|
|
}
|
|
|
|
protected function sub_test_grade_category_aggregation_uses_extracredit() {
|
|
|
|
$this->assertTrue(\grade_category::aggregation_uses_extracredit(GRADE_AGGREGATE_WEIGHTED_MEAN2));
|
|
$this->assertTrue(\grade_category::aggregation_uses_extracredit(GRADE_AGGREGATE_EXTRACREDIT_MEAN));
|
|
$this->assertTrue(\grade_category::aggregation_uses_extracredit(GRADE_AGGREGATE_SUM));
|
|
|
|
$this->assertFalse(\grade_category::aggregation_uses_extracredit(GRADE_AGGREGATE_WEIGHTED_MEAN));
|
|
$this->assertFalse(\grade_category::aggregation_uses_extracredit(GRADE_AGGREGATE_MAX));
|
|
$this->assertFalse(\grade_category::aggregation_uses_extracredit(GRADE_AGGREGATE_MEAN));
|
|
$this->assertFalse(\grade_category::aggregation_uses_extracredit(GRADE_AGGREGATE_MEDIAN));
|
|
$this->assertFalse(\grade_category::aggregation_uses_extracredit(GRADE_AGGREGATE_MIN));
|
|
$this->assertFalse(\grade_category::aggregation_uses_extracredit(GRADE_AGGREGATE_MODE));
|
|
}
|
|
|
|
/**
|
|
* Test for category total visibility.
|
|
*/
|
|
protected function sub_test_grade_category_total_visibility() {
|
|
// 15 is a manual grade item in grade_categories[5].
|
|
$category = new \grade_category($this->grade_categories[5], true);
|
|
$gradeitem = new \grade_item($this->grade_items[15], true);
|
|
|
|
// Hide grade category.
|
|
$category->set_hidden(true, true);
|
|
$this->assertTrue($category->is_hidden());
|
|
// Category total is hidden.
|
|
$categorytotal = $category->get_grade_item();
|
|
$this->assertTrue($categorytotal->is_hidden());
|
|
// Manual grade is hidden.
|
|
$gradeitem->update_from_db();
|
|
$this->assertTrue($gradeitem->is_hidden());
|
|
|
|
// Unhide manual grade item.
|
|
$gradeitem->set_hidden(false);
|
|
$this->assertFalse($gradeitem->is_hidden());
|
|
// Category is unhidden.
|
|
$category->update_from_db();
|
|
$this->assertFalse($category->is_hidden());
|
|
// Category total remain hidden.
|
|
$categorytotal = $category->get_grade_item();
|
|
$this->assertTrue($categorytotal->is_hidden());
|
|
|
|
// Edit manual grade item.
|
|
$this->assertFalse($gradeitem->is_locked());
|
|
$gradeitem->set_locked(true);
|
|
$gradeitem->update_from_db();
|
|
$this->assertTrue($gradeitem->is_locked());
|
|
// Category total should still be hidden.
|
|
$category->update_from_db();
|
|
$categorytotal = $category->get_grade_item();
|
|
$this->assertTrue($categorytotal->is_hidden());
|
|
}
|
|
}
|