Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 39 and 401]

   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   * Unit tests for grade/report/lib.php.
  19   *
  20   * @package  core_grades
  21   * @category phpunit
  22   * @author   Andrew Davis
  23   * @license  http://www.gnu.org/copyleft/gpl.html GNU Public License
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  global $CFG;
  29  require_once($CFG->dirroot.'/grade/lib.php');
  30  require_once($CFG->dirroot.'/grade/report/lib.php');
  31  
  32  /**
  33   * A test class used to test grade_report, the abstract grade report parent class
  34   */
  35  class grade_report_mock extends grade_report {
  36      public function __construct($courseid, $gpr, $context, $user) {
  37          parent::__construct($courseid, $gpr, $context);
  38          $this->user = $user;
  39      }
  40  
  41      /**
  42       * A wrapper around blank_hidden_total_and_adjust_bounds() to allow test code to call it directly
  43       */
  44      public function blank_hidden_total_and_adjust_bounds($courseid, $courseitem, $finalgrade) {
  45          return parent::blank_hidden_total_and_adjust_bounds($courseid, $courseitem, $finalgrade);
  46      }
  47  
  48      /**
  49       * Implementation of the abstract method process_data()
  50       */
  51      public function process_data($data) {
  52      }
  53  
  54      /**
  55       * Implementation of the abstract method process_action()
  56       */
  57      public function process_action($target, $action) {
  58      }
  59  }
  60  
  61  /**
  62   * Tests grade_report, the parent class for all grade reports.
  63   */
  64  class reportlib_test extends advanced_testcase {
  65  
  66      /**
  67       * Tests grade_report::blank_hidden_total_and_adjust_bounds()
  68       */
  69      public function test_blank_hidden_total_and_adjust_bounds() {
  70          global $DB;
  71  
  72          $this->resetAfterTest(true);
  73  
  74          $student = $this->getDataGenerator()->create_user();
  75          $this->setUser($student);
  76  
  77          // Create a course and two activities.
  78          // One activity will be hidden.
  79          $course = $this->getDataGenerator()->create_course();
  80          $coursegradeitem = grade_item::fetch_course_item($course->id);
  81          $coursecontext = context_course::instance($course->id);
  82  
  83          $data = $this->getDataGenerator()->create_module('data', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
  84          $datacm = get_coursemodule_from_id('data', $data->cmid);
  85  
  86          $forum = $this->getDataGenerator()->create_module('forum', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
  87          $forumcm = get_coursemodule_from_id('forum', $forum->cmid);
  88  
  89          // Insert student grades for the two activities.
  90          $gi = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'data', 'iteminstance' => $data->id, 'courseid' => $course->id));
  91          $datagrade = 50;
  92          $grade_grade = new grade_grade();
  93          $grade_grade->itemid = $gi->id;
  94          $grade_grade->userid = $student->id;
  95          $grade_grade->rawgrade = $datagrade;
  96          $grade_grade->finalgrade = $datagrade;
  97          $grade_grade->rawgrademax = 100;
  98          $grade_grade->rawgrademin = 0;
  99          $grade_grade->timecreated = time();
 100          $grade_grade->timemodified = time();
 101          $grade_grade->insert();
 102  
 103          $gi = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'forum', 'iteminstance' => $forum->id, 'courseid' => $course->id));
 104          $forumgrade = 70;
 105          $grade_grade = new grade_grade();
 106          $grade_grade->itemid = $gi->id;
 107          $grade_grade->userid = $student->id;
 108          $grade_grade->rawgrade = $forumgrade;
 109          $grade_grade->finalgrade = $forumgrade;
 110          $grade_grade->rawgrademax = 100;
 111          $grade_grade->rawgrademin = 0;
 112          $grade_grade->timecreated = time();
 113          $grade_grade->timemodified = time();
 114          $grade_grade->insert();
 115  
 116          // Hide the database activity.
 117          set_coursemodule_visible($datacm->id, 0);
 118  
 119          $gpr = new grade_plugin_return(array('type' => 'report', 'courseid' => $course->id));
 120          $report = new grade_report_mock($course->id, $gpr, $coursecontext, $student);
 121  
 122          // Should return the supplied student total grade regardless of hiding.
 123          $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN);
 124          $result = $report->blank_hidden_total_and_adjust_bounds($course->id, $coursegradeitem, $datagrade + $forumgrade);
 125          $this->assertEquals(array('grade' => $datagrade + $forumgrade,
 126                                    'grademax' => $coursegradeitem->grademax,
 127                                    'grademin' => $coursegradeitem->grademin,
 128                                    'aggregationstatus' => 'unknown',
 129                                    'aggregationweight' => null), $result);
 130          // Should blank the student total as course grade depends on a hidden item.
 131          $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN);
 132          $result = $report->blank_hidden_total_and_adjust_bounds($course->id, $coursegradeitem, $datagrade + $forumgrade);
 133          $this->assertEquals(array('grade' => null,
 134                                    'grademax' => $coursegradeitem->grademax,
 135                                    'grademin' => $coursegradeitem->grademin,
 136                                    'aggregationstatus' => 'unknown',
 137                                    'aggregationweight' => null), $result);
 138  
 139          // Should return the course total minus the hidden database activity grade.
 140          $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN);
 141          $result = $report->blank_hidden_total_and_adjust_bounds($course->id, $coursegradeitem, $datagrade + $forumgrade);
 142          $this->assertEquals(array('grade' => floatval($forumgrade),
 143                                    'grademax' => $coursegradeitem->grademax,
 144                                    'grademin' => $coursegradeitem->grademin,
 145                                    'aggregationstatus' => 'unknown',
 146                                    'aggregationweight' => null), $result);
 147  
 148          // Note: we cannot simply hide modules and call $report->blank_hidden_total() again.
 149          // It stores grades in a static variable so $report->blank_hidden_total() will return incorrect totals
 150          // In practice this isn't a problem. Grade visibility isn't altered mid-request outside of the unit tests.
 151  
 152          // Add a second course to test:
 153          // 1) How a course with no visible activities behaves.
 154          // 2) That $report->blank_hidden_total() correctly moves on to the new course.
 155          $course = $this->getDataGenerator()->create_course();
 156          $coursegradeitem = grade_item::fetch_course_item($course->id);
 157          $coursecontext = context_course::instance($course->id);
 158  
 159          $data = $this->getDataGenerator()->create_module('data', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
 160          $datacm = get_coursemodule_from_id('data', $data->cmid);
 161  
 162          $forum = $this->getDataGenerator()->create_module('forum', array('assessed' => 1, 'scale' => 100, 'course' => $course->id));
 163          $forumcm = get_coursemodule_from_id('forum', $forum->cmid);
 164  
 165          $gi = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'data', 'iteminstance' => $data->id, 'courseid' => $course->id));
 166          $datagrade = 50;
 167          $grade_grade = new grade_grade();
 168          $grade_grade->itemid = $gi->id;
 169          $grade_grade->userid = $student->id;
 170          $grade_grade->rawgrade = $datagrade;
 171          $grade_grade->finalgrade = $datagrade;
 172          $grade_grade->rawgrademax = 100;
 173          $grade_grade->rawgrademin = 0;
 174          $grade_grade->timecreated = time();
 175          $grade_grade->timemodified = time();
 176          $grade_grade->insert();
 177  
 178          $gi = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'forum', 'iteminstance' => $forum->id, 'courseid' => $course->id));
 179          $forumgrade = 70;
 180          $grade_grade = new grade_grade();
 181          $grade_grade->itemid = $gi->id;
 182          $grade_grade->userid = $student->id;
 183          $grade_grade->rawgrade = $forumgrade;
 184          $grade_grade->finalgrade = $forumgrade;
 185          $grade_grade->rawgrademax = 100;
 186          $grade_grade->rawgrademin = 0;
 187          $grade_grade->timecreated = time();
 188          $grade_grade->timemodified = time();
 189          $grade_grade->insert();
 190  
 191          // Hide both activities.
 192          set_coursemodule_visible($datacm->id, 0);
 193          set_coursemodule_visible($forumcm->id, 0);
 194  
 195          $gpr = new grade_plugin_return(array('type' => 'report', 'courseid' => $course->id));
 196          $report = new grade_report_mock($course->id, $gpr, $coursecontext, $student);
 197  
 198          // Should return the supplied student total grade regardless of hiding.
 199          $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN);
 200          $result = $report->blank_hidden_total_and_adjust_bounds($course->id, $coursegradeitem, $datagrade + $forumgrade);
 201          $this->assertEquals(array('grade' => $datagrade + $forumgrade,
 202                                    'grademax' => $coursegradeitem->grademax,
 203                                    'grademin' => $coursegradeitem->grademin,
 204                                    'aggregationstatus' => 'unknown',
 205                                    'aggregationweight' => null), $result);
 206  
 207          // Should blank the student total as course grade depends on a hidden item.
 208          $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN);
 209          $result = $report->blank_hidden_total_and_adjust_bounds($course->id, $coursegradeitem, $datagrade + $forumgrade);
 210          $this->assertEquals(array('grade' => null,
 211                                    'grademax' => $coursegradeitem->grademax,
 212                                    'grademin' => $coursegradeitem->grademin,
 213                                    'aggregationstatus' => 'unknown',
 214                                    'aggregationweight' => null), $result);
 215  
 216          // Should return the course total minus the hidden activity grades.
 217          // They are both hidden so should return null.
 218          $report->showtotalsifcontainhidden = array($course->id => GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN);
 219          $result = $report->blank_hidden_total_and_adjust_bounds($course->id, $coursegradeitem, $datagrade + $forumgrade);
 220          $this->assertEquals(array('grade' => null,
 221                                    'grademax' => $coursegradeitem->grademax,
 222                                    'grademin' => $coursegradeitem->grademin,
 223                                    'aggregationstatus' => 'unknown',
 224                                    'aggregationweight' => null), $result);
 225      }
 226  }