Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
}