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