Differences Between: [Versions 310 and 311] [Versions 39 and 311]
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 grading evaluation method "best" 19 * 20 * @package workshopeval_best 21 * @category test 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 namespace workshopeval_best; 26 27 use workshop; 28 use workshop_best_evaluation; 29 30 defined('MOODLE_INTERNAL') || die(); 31 32 // Include the code to test 33 global $CFG; 34 require_once($CFG->dirroot . '/mod/workshop/locallib.php'); 35 require_once($CFG->dirroot . '/mod/workshop/eval/best/lib.php'); 36 require_once($CFG->libdir . '/gradelib.php'); 37 38 /** 39 * Unit tests for grading evaluation lib.php 40 */ 41 class lib_test extends \advanced_testcase { 42 43 /** workshop instance emulation */ 44 protected $workshop; 45 46 /** instance of the grading evaluator being tested */ 47 protected $evaluator; 48 49 /** 50 * Setup testing environment 51 */ 52 protected function setUp(): void { 53 parent::setUp(); 54 $this->resetAfterTest(); 55 $this->setAdminUser(); 56 $course = $this->getDataGenerator()->create_course(); 57 $workshop = $this->getDataGenerator()->create_module('workshop', array('evaluation' => 'best', 'course' => $course)); 58 $cm = get_fast_modinfo($course)->instances['workshop'][$workshop->id]; 59 $this->workshop = new workshop($workshop, $cm, $course); 60 $this->evaluator = new testable_workshop_best_evaluation($this->workshop); 61 } 62 63 protected function tearDown(): void { 64 $this->workshop = null; 65 $this->evaluator = null; 66 parent::tearDown(); 67 } 68 69 public function test_normalize_grades() { 70 // fixture set-up 71 $assessments = array(); 72 $assessments[1] = (object)array( 73 'dimgrades' => array(3 => 1.0000, 4 => 13.42300), 74 ); 75 $assessments[3] = (object)array( 76 'dimgrades' => array(3 => 2.0000, 4 => 19.1000), 77 ); 78 $assessments[7] = (object)array( 79 'dimgrades' => array(3 => 3.0000, 4 => 0.00000), 80 ); 81 $diminfo = array( 82 3 => (object)array('min' => 1, 'max' => 3), 83 4 => (object)array('min' => 0, 'max' => 20), 84 ); 85 // exercise SUT 86 $norm = $this->evaluator->normalize_grades($assessments, $diminfo); 87 // validate 88 $this->assertEquals(gettype($norm), 'array'); 89 // the following grades from a scale 90 $this->assertEquals($norm[1]->dimgrades[3], 0); 91 $this->assertEquals($norm[3]->dimgrades[3], 50); 92 $this->assertEquals($norm[7]->dimgrades[3], 100); 93 // the following grades from an interval 0 - 20 94 $this->assertEquals($norm[1]->dimgrades[4], grade_floatval(13.423 / 20 * 100)); 95 $this->assertEquals($norm[3]->dimgrades[4], grade_floatval(19.1 / 20 * 100)); 96 $this->assertEquals($norm[7]->dimgrades[4], 0); 97 } 98 99 public function test_normalize_grades_max_equals_min() { 100 // fixture set-up 101 $assessments = array(); 102 $assessments[1] = (object)array( 103 'dimgrades' => array(3 => 100.0000), 104 ); 105 $diminfo = array( 106 3 => (object)array('min' => 100, 'max' => 100), 107 ); 108 // exercise SUT 109 $norm = $this->evaluator->normalize_grades($assessments, $diminfo); 110 // validate 111 $this->assertEquals(gettype($norm), 'array'); 112 $this->assertEquals($norm[1]->dimgrades[3], 100); 113 } 114 115 public function test_average_assessment_same_weights() { 116 // fixture set-up 117 $assessments = array(); 118 $assessments[18] = (object)array( 119 'weight' => 1, 120 'dimgrades' => array(1 => 50, 2 => 33.33333), 121 ); 122 $assessments[16] = (object)array( 123 'weight' => 1, 124 'dimgrades' => array(1 => 0, 2 => 66.66667), 125 ); 126 // exercise SUT 127 $average = $this->evaluator->average_assessment($assessments); 128 // validate 129 $this->assertEquals(gettype($average->dimgrades), 'array'); 130 $this->assertEquals(grade_floatval($average->dimgrades[1]), grade_floatval(25)); 131 $this->assertEquals(grade_floatval($average->dimgrades[2]), grade_floatval(50)); 132 } 133 134 public function test_average_assessment_different_weights() { 135 // fixture set-up 136 $assessments = array(); 137 $assessments[11] = (object)array( 138 'weight' => 1, 139 'dimgrades' => array(3 => 10.0, 4 => 13.4, 5 => 95.0), 140 ); 141 $assessments[13] = (object)array( 142 'weight' => 3, 143 'dimgrades' => array(3 => 11.0, 4 => 10.1, 5 => 92.0), 144 ); 145 $assessments[17] = (object)array( 146 'weight' => 1, 147 'dimgrades' => array(3 => 11.0, 4 => 8.1, 5 => 88.0), 148 ); 149 // exercise SUT 150 $average = $this->evaluator->average_assessment($assessments); 151 // validate 152 $this->assertEquals(gettype($average->dimgrades), 'array'); 153 $this->assertEquals(grade_floatval($average->dimgrades[3]), grade_floatval((10.0 + 11.0*3 + 11.0)/5)); 154 $this->assertEquals(grade_floatval($average->dimgrades[4]), grade_floatval((13.4 + 10.1*3 + 8.1)/5)); 155 $this->assertEquals(grade_floatval($average->dimgrades[5]), grade_floatval((95.0 + 92.0*3 + 88.0)/5)); 156 } 157 158 public function test_average_assessment_noweight() { 159 // fixture set-up 160 $assessments = array(); 161 $assessments[11] = (object)array( 162 'weight' => 0, 163 'dimgrades' => array(3 => 10.0, 4 => 13.4, 5 => 95.0), 164 ); 165 $assessments[17] = (object)array( 166 'weight' => 0, 167 'dimgrades' => array(3 => 11.0, 4 => 8.1, 5 => 88.0), 168 ); 169 // exercise SUT 170 $average = $this->evaluator->average_assessment($assessments); 171 // validate 172 $this->assertNull($average); 173 } 174 175 public function test_weighted_variance() { 176 // fixture set-up 177 $assessments[11] = (object)array( 178 'weight' => 1, 179 'dimgrades' => array(3 => 11, 4 => 2), 180 ); 181 $assessments[13] = (object)array( 182 'weight' => 3, 183 'dimgrades' => array(3 => 11, 4 => 4), 184 ); 185 $assessments[17] = (object)array( 186 'weight' => 2, 187 'dimgrades' => array(3 => 11, 4 => 5), 188 ); 189 $assessments[20] = (object)array( 190 'weight' => 1, 191 'dimgrades' => array(3 => 11, 4 => 7), 192 ); 193 $assessments[25] = (object)array( 194 'weight' => 1, 195 'dimgrades' => array(3 => 11, 4 => 9), 196 ); 197 // exercise SUT 198 $variance = $this->evaluator->weighted_variance($assessments); 199 // validate 200 // dimension [3] have all the grades equal to 11 201 $this->assertEquals($variance[3], 0); 202 // dimension [4] represents data 2, 4, 4, 4, 5, 5, 7, 9 having stdev=2 (stdev is sqrt of variance) 203 $this->assertEquals($variance[4], 4); 204 } 205 206 public function test_assessments_distance_zero() { 207 // fixture set-up 208 $diminfo = array( 209 3 => (object)array('weight' => 1, 'min' => 0, 'max' => 100, 'variance' => 12.34567), 210 4 => (object)array('weight' => 1, 'min' => 1, 'max' => 5, 'variance' => 98.76543), 211 ); 212 $assessment1 = (object)array('dimgrades' => array(3 => 15, 4 => 2)); 213 $assessment2 = (object)array('dimgrades' => array(3 => 15, 4 => 2)); 214 $settings = (object)array('comparison' => 5); 215 // exercise SUT and validate 216 $this->assertEquals($this->evaluator->assessments_distance($assessment1, $assessment2, $diminfo, $settings), 0); 217 } 218 219 public function test_assessments_distance_equals() { 220 /* 221 // fixture set-up 222 $diminfo = array( 223 3 => (object)array('weight' => 1, 'min' => 0, 'max' => 100, 'variance' => 12.34567), 224 4 => (object)array('weight' => 1, 'min' => 0, 'max' => 100, 'variance' => 12.34567), 225 ); 226 $assessment1 = (object)array('dimgrades' => array(3 => 25, 4 => 4)); 227 $assessment2 = (object)array('dimgrades' => array(3 => 75, 4 => 2)); 228 $referential = (object)array('dimgrades' => array(3 => 50, 4 => 3)); 229 $settings = (object)array('comparison' => 5); 230 // exercise SUT and validate 231 $this->assertEquals($this->evaluator->assessments_distance($assessment1, $referential, $diminfo, $settings), 232 $this->evaluator->assessments_distance($assessment2, $referential, $diminfo, $settings)); 233 */ 234 // fixture set-up 235 $diminfo = array( 236 1 => (object)array('min' => 0, 'max' => 2, 'weight' => 1, 'variance' => 625), 237 2 => (object)array('min' => 0, 'max' => 3, 'weight' => 1, 'variance' => 277.7778888889), 238 ); 239 $assessment1 = (object)array('dimgrades' => array(1 => 0, 2 => 66.66667)); 240 $assessment2 = (object)array('dimgrades' => array(1 => 50, 2 => 33.33333)); 241 $referential = (object)array('dimgrades' => array(1 => 25, 2 => 50)); 242 $settings = (object)array('comparison' => 9); 243 // exercise SUT and validate 244 $this->assertEquals($this->evaluator->assessments_distance($assessment1, $referential, $diminfo, $settings), 245 $this->evaluator->assessments_distance($assessment2, $referential, $diminfo, $settings)); 246 247 } 248 249 public function test_assessments_distance_zero_variance() { 250 // Fixture set-up: an assessment form of the strategy "Number of errors", 251 // three assertions, same weight. 252 $diminfo = array( 253 1 => (object)array('min' => 0, 'max' => 1, 'weight' => 1), 254 2 => (object)array('min' => 0, 'max' => 1, 'weight' => 1), 255 3 => (object)array('min' => 0, 'max' => 1, 'weight' => 1), 256 ); 257 258 // Simulate structure returned by {@link workshop_best_evaluation::prepare_data_from_recordset()} 259 $assessments = array( 260 // The first assessment has weight 0 and the assessment was No, No, No. 261 10 => (object)array( 262 'assessmentid' => 10, 263 'weight' => 0, 264 'reviewerid' => 56, 265 'gradinggrade' => null, 266 'submissionid' => 99, 267 'dimgrades' => array( 268 1 => 0, 269 2 => 0, 270 3 => 0, 271 ), 272 ), 273 // The second assessment has weight 1 and assessments was Yes, Yes, Yes. 274 20 => (object)array( 275 'assessmentid' => 20, 276 'weight' => 1, 277 'reviewerid' => 76, 278 'gradinggrade' => null, 279 'submissionid' => 99, 280 'dimgrades' => array( 281 1 => 1, 282 2 => 1, 283 3 => 1, 284 ), 285 ), 286 // The third assessment has weight 1 and assessments was Yes, Yes, Yes too. 287 30 => (object)array( 288 'assessmentid' => 30, 289 'weight' => 1, 290 'reviewerid' => 97, 291 'gradinggrade' => null, 292 'submissionid' => 99, 293 'dimgrades' => array( 294 1 => 1, 295 2 => 1, 296 3 => 1, 297 ), 298 ), 299 ); 300 301 // Process assessments in the same way as in the {@link workshop_best_evaluation::process_assessments()} 302 $assessments = $this->evaluator->normalize_grades($assessments, $diminfo); 303 $average = $this->evaluator->average_assessment($assessments); 304 $variances = $this->evaluator->weighted_variance($assessments); 305 foreach ($variances as $dimid => $variance) { 306 $diminfo[$dimid]->variance = $variance; 307 } 308 309 // Simulate the chosen comparison of assessments "fair" (does not really matter here but we need something). 310 $settings = (object)array('comparison' => 5); 311 312 // Exercise SUT: for every assessment, calculate its distance from the average one. 313 $distances = array(); 314 foreach ($assessments as $asid => $assessment) { 315 $distances[$asid] = $this->evaluator->assessments_distance($assessment, $average, $diminfo, $settings); 316 } 317 318 // Validate: the first assessment is far far away from the average one ... 319 $this->assertTrue($distances[10] > 0); 320 // ... while the two others were both picked as the referential ones. 321 $this->assertTrue($distances[20] == 0); 322 $this->assertTrue($distances[30] == 0); 323 } 324 } 325 326 327 /** 328 * Test subclass that makes all the protected methods we want to test public. 329 */ 330 class testable_workshop_best_evaluation extends workshop_best_evaluation { 331 332 public function normalize_grades(array $assessments, array $diminfo) { 333 return parent::normalize_grades($assessments, $diminfo); 334 } 335 public function average_assessment(array $assessments) { 336 return parent::average_assessment($assessments); 337 } 338 public function weighted_variance(array $assessments) { 339 return parent::weighted_variance($assessments); 340 } 341 public function assessments_distance(\stdClass $assessment, \stdClass $referential, array $diminfo, \stdClass $settings) { 342 return parent::assessments_distance($assessment, $referential, $diminfo, $settings); 343 } 344 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body