Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]

   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 Accumulative grading strategy logic
  19   *
  20   * @package    workshopform_accumulative
  21   * @category   phpunit
  22   * @copyright  2009 David Mudrak <david.mudrak@gmail.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  // Include the code to test
  29  global $CFG;
  30  require_once($CFG->dirroot . '/mod/workshop/locallib.php');
  31  require_once($CFG->dirroot . '/mod/workshop/form/accumulative/lib.php');
  32  
  33  
  34  class workshop_accumulative_strategy_testcase extends advanced_testcase {
  35      /** workshop instance emulation */
  36      protected $workshop;
  37  
  38      /** @var testable_workshop_accumulative_strategy instance of the strategy logic class being tested */
  39      protected $strategy;
  40  
  41      /**
  42       * Setup testing environment
  43       */
  44      protected function setUp(): void {
  45          parent::setUp();
  46          $this->resetAfterTest();
  47          $this->setAdminUser();
  48          $course = $this->getDataGenerator()->create_course();
  49          $workshop = $this->getDataGenerator()->create_module('workshop', array('strategy' => 'accumulative', 'course' => $course));
  50          $cm = get_fast_modinfo($course)->instances['workshop'][$workshop->id];
  51          $this->workshop = new workshop($workshop, $cm, $course);
  52          $this->strategy = new testable_workshop_accumulative_strategy($this->workshop);
  53      }
  54  
  55      protected function tearDown(): void {
  56          $this->workshop = null;
  57          $this->strategy = null;
  58          parent::tearDown();
  59      }
  60  
  61      public function test_calculate_peer_grade_null_grade() {
  62          // fixture set-up
  63          $this->strategy->dimensions = array();
  64          $grades = array();
  65          // exercise SUT
  66          $suggested = $this->strategy->calculate_peer_grade($grades);
  67          // validate
  68          $this->assertNull($suggested);
  69      }
  70  
  71      public function test_calculate_peer_grade_one_numerical() {
  72          // fixture set-up
  73          $this->strategy->dimensions[1003] = (object)array('grade' => '20', 'weight' => '1');
  74          $grades[] = (object)array('dimensionid' => 1003, 'grade' => '5.00000');
  75          // exercise SUT
  76          $suggested = $this->strategy->calculate_peer_grade($grades);
  77          // validate
  78          $this->assertEquals(grade_floatval(5/20 * 100), $suggested);
  79      }
  80  
  81      public function test_calculate_peer_grade_negative_weight() {
  82          // fixture set-up
  83          $this->strategy->dimensions[1003] = (object)array('grade' => '20', 'weight' => '-1');
  84          $grades[] = (object)array('dimensionid' => 1003, 'grade' => '20');
  85          // exercise SUT
  86          $this->expectException(coding_exception::class);
  87          $suggested = $this->strategy->calculate_peer_grade($grades);
  88      }
  89  
  90      public function test_calculate_peer_grade_one_numerical_weighted() {
  91          // fixture set-up
  92          $this->strategy->dimensions[1003] = (object)array('grade' => '20', 'weight' => '3');
  93          $grades[] = (object)array('dimensionid' => '1003', 'grade' => '5');
  94          // exercise SUT
  95          $suggested = $this->strategy->calculate_peer_grade($grades);
  96          // validate
  97          $this->assertEquals(grade_floatval(5/20 * 100), $suggested);
  98      }
  99  
 100      public function test_calculate_peer_grade_three_numericals_same_weight() {
 101          // fixture set-up
 102          $this->strategy->dimensions[1003] = (object)array('grade' => '20', 'weight' => '2');
 103          $this->strategy->dimensions[1004] = (object)array('grade' => '100', 'weight' => '2');
 104          $this->strategy->dimensions[1005] = (object)array('grade' => '10', 'weight' => '2');
 105          $grades[] = (object)array('dimensionid' => 1003, 'grade' => '11.00000');
 106          $grades[] = (object)array('dimensionid' => 1004, 'grade' => '87.00000');
 107          $grades[] = (object)array('dimensionid' => 1005, 'grade' => '10.00000');
 108  
 109          // exercise SUT
 110          $suggested = $this->strategy->calculate_peer_grade($grades);
 111  
 112          // validate
 113          $this->assertEquals(grade_floatval((11/20 + 87/100 + 10/10)/3 * 100), $suggested);
 114      }
 115  
 116      public function test_calculate_peer_grade_three_numericals_different_weights() {
 117          // fixture set-up
 118          $this->strategy->dimensions[1003] = (object)array('grade' => '15', 'weight' => 3);
 119          $this->strategy->dimensions[1004] = (object)array('grade' => '80', 'weight' => 1);
 120          $this->strategy->dimensions[1005] = (object)array('grade' => '5', 'weight' => 2);
 121          $grades[] = (object)array('dimensionid' => 1003, 'grade' => '7.00000');
 122          $grades[] = (object)array('dimensionid' => 1004, 'grade' => '66.00000');
 123          $grades[] = (object)array('dimensionid' => 1005, 'grade' => '4.00000');
 124  
 125          // exercise SUT
 126          $suggested = $this->strategy->calculate_peer_grade($grades);
 127  
 128          // validate
 129          $this->assertEquals(grade_floatval((7/15*3 + 66/80*1 + 4/5*2)/6 * 100), $suggested);
 130      }
 131  
 132      public function test_calculate_peer_grade_one_scale_max() {
 133          $this->resetAfterTest(true);
 134  
 135          // fixture set-up
 136          $scale11 = $this->getDataGenerator()->create_scale(array('scale'=>'E,D,C,B,A', 'id'=>11));
 137          $this->strategy->dimensions[1008] = (object)array('grade' => (-$scale11->id), 'weight' => 1);
 138          $grades[] = (object)array('dimensionid' => 1008, 'grade' => '5.00000');
 139  
 140          // exercise SUT
 141          $suggested = $this->strategy->calculate_peer_grade($grades);
 142  
 143          // validate
 144          $this->assertEquals(100.00000, $suggested);
 145      }
 146  
 147      public function test_calculate_peer_grade_one_scale_min_with_scale_caching() {
 148          $this->resetAfterTest(true);
 149  
 150          // fixture set-up
 151          $scale11 = $this->getDataGenerator()->create_scale(array('scale'=>'E,D,C,B,A', 'id'=>11));
 152          $this->strategy->dimensions[1008] = (object)array('grade' => (-$scale11->id), 'weight' => 1);
 153          $grades[] = (object)array('dimensionid' => 1008, 'grade' => '1.00000');
 154  
 155          // exercise SUT
 156          $suggested = $this->strategy->calculate_peer_grade($grades);
 157  
 158          // validate
 159          $this->assertEquals(0.00000, $suggested);
 160      }
 161  
 162      public function test_calculate_peer_grade_two_scales_weighted() {
 163          $this->resetAfterTest(true);
 164          // fixture set-up
 165          $scale13 = $this->getDataGenerator()->create_scale(array('scale'=>'Poor,Good,Excellent', 'id'=>13));
 166          $scale17 = $this->getDataGenerator()->create_scale(array('scale'=>'-,*,**,***,****,*****,******', 'id'=>17));
 167          $this->strategy->dimensions[1012] = (object)array('grade' => (-$scale13->id), 'weight' => 2);
 168          $this->strategy->dimensions[1019] = (object)array('grade' => (-$scale17->id), 'weight' => 3);
 169          $grades[] = (object)array('dimensionid' => 1012, 'grade' => '2.00000'); // "Good"
 170          $grades[] = (object)array('dimensionid' => 1019, 'grade' => '5.00000'); // "****"
 171  
 172          // exercise SUT
 173          $suggested = $this->strategy->calculate_peer_grade($grades);
 174  
 175          // validate
 176          $this->assertEquals(grade_floatval((1/2*2 + 4/6*3)/5 * 100), $suggested);
 177      }
 178  
 179      public function test_calculate_peer_grade_scale_exception() {
 180          $this->resetAfterTest(true);
 181          // fixture set-up
 182          $scale13 = $this->getDataGenerator()->create_scale(array('scale'=>'Poor,Good,Excellent', 'id'=>13));
 183          $this->strategy->dimensions[1012] = (object)array('grade' => (-$scale13->id), 'weight' => 1);
 184          $grades[] = (object)array('dimensionid' => 1012, 'grade' => '4.00000'); // exceeds the number of scale items
 185  
 186          // Exercise SUT.
 187          $this->expectException(coding_exception::class);
 188          $suggested = $this->strategy->calculate_peer_grade($grades);
 189      }
 190  }
 191  
 192  
 193  /**
 194   * Test subclass that makes all the protected methods we want to test public
 195   */
 196  class testable_workshop_accumulative_strategy extends workshop_accumulative_strategy {
 197  
 198      /** allows to set dimensions manually */
 199      public $dimensions = array();
 200  
 201      /**
 202       * This is where the calculation of suggested grade for submission is done
 203       */
 204      public function calculate_peer_grade(array $grades) {
 205          return parent::calculate_peer_grade($grades);
 206      }
 207  }