73f623de7966cac3cc9f2e1e1284f32e4b229698
[moodle.git] / lib / tests / indicators_test.php
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/>.
17 /**
18  * Unit tests for core indicators.
19  *
20  * @package   core
21  * @category  phpunit
22  * @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
23  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 defined('MOODLE_INTERNAL') || die();
28 require_once(__DIR__ . '/../../analytics/tests/fixtures/test_target_shortname.php');
29 require_once(__DIR__ . '/../../admin/tool/log/store/standard/tests/fixtures/event.php');
30 require_once(__DIR__ . '/../../lib/enrollib.php');
32 /**
33  * Unit tests for core indicators.
34  *
35  * @package   core
36  * @category  phpunit
37  * @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
38  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39  */
40 class core_analytics_indicators_testcase extends advanced_testcase {
42     /**
43      * Test all core indicators.
44      *
45      * Single method as it is significantly faster (from 13s to 5s) than having separate
46      * methods because of preventResetByRollback.
47      *
48      * @return void
49      */
50     public function test_core_indicators() {
52         $this->preventResetByRollback();
53         $this->resetAfterTest(true);
54         $this->setAdminuser();
56         set_config('enabled_stores', 'logstore_standard', 'tool_log');
57         set_config('buffersize', 0, 'logstore_standard');
59         $user1 = $this->getDataGenerator()->create_user();
60         $user2 = $this->getDataGenerator()->create_user();
62         // Test any access after end.
63         $params = array(
64             'startdate' => mktime(0, 0, 0, 10, 24, 2015),
65             'enddate' => mktime(0, 0, 0, 10, 24, 2016)
66         );
67         $course = $this->getDataGenerator()->create_course($params);
68         $coursecontext = \context_course::instance($course->id);
69         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
71         $indicator = new \core\analytics\indicator\any_access_after_end();
73         $sampleids = array($user1->id => $user1->id, $user2->id => $user2->id);
74         $data = array($user1->id => array(
75             'context' => $coursecontext,
76             'course' => $course,
77             'user' => $user1
78         ));
79         $data[$user2->id] = $data[$user1->id];
80         $data[$user2->id]['user'] = $user2;
81         $indicator->add_sample_data($data);
83         $values = $indicator->calculate($sampleids, 'notrelevanthere');
84         $this->assertEquals($indicator::get_min_value(), $values[$user1->id][0]);
85         $this->assertEquals($indicator::get_min_value(), $values[$user2->id][0]);
87         \logstore_standard\event\unittest_executed::create(
88             array('context' => $coursecontext, 'userid' => $user1->id))->trigger();
89         $values = $indicator->calculate($sampleids, 'notrelevanthere');
90         $this->assertEquals($indicator::get_max_value(), $values[$user1->id][0]);
91         $this->assertEquals($indicator::get_min_value(), $values[$user2->id][0]);
93         // Test any access before start.
94         $params = array(
95             'startdate' => 9999999998,
96             'enddate' => 9999999999
97         );
98         // Resetting $course var.
99         $course = $this->getDataGenerator()->create_course($params);
100         $coursecontext = \context_course::instance($course->id);
101         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
103         $indicator = new \core\analytics\indicator\any_access_before_start();
105         $sampleids = array($user1->id => $user1->id, $user2->id => $user2->id);
106         $data = array($user1->id => array(
107             'context' => $coursecontext,
108             'course' => $course,
109             'user' => $user1
110         ));
111         $data[$user2->id] = $data[$user1->id];
112         $data[$user2->id]['user'] = $user2;
113         $indicator->add_sample_data($data);
115         $values = $indicator->calculate($sampleids, 'notrelevanthere');
116         $this->assertEquals($indicator::get_min_value(), $values[$user1->id][0]);
117         $this->assertEquals($indicator::get_min_value(), $values[$user2->id][0]);
119         \logstore_standard\event\unittest_executed::create(
120             array('context' => $coursecontext, 'userid' => $user1->id))->trigger();
121         $values = $indicator->calculate($sampleids, 'notrelevanthere');
122         $this->assertEquals($indicator::get_max_value(), $values[$user1->id][0]);
123         $this->assertEquals($indicator::get_min_value(), $values[$user2->id][0]);
125         // Test any write action.
126         $course1 = $this->getDataGenerator()->create_course();
127         $coursecontext1 = \context_course::instance($course1->id);
128         $course2 = $this->getDataGenerator()->create_course();
129         $coursecontext2 = \context_course::instance($course2->id);
130         $this->getDataGenerator()->enrol_user($user1->id, $course2->id);
132         $indicator = new \core\analytics\indicator\any_write_action();
134         $sampleids = array($user1->id => $user1->id, $user2->id => $user2->id);
135         $data = array($user1->id => array(
136             'context' => $coursecontext1,
137             'course' => $course1,
138             'user' => $user1
139         ));
140         $data[$user2->id] = $data[$user1->id];
141         $data[$user2->id]['user'] = $user2;
142         $indicator->add_sample_data($data);
144         $values = $indicator->calculate($sampleids, 'user');
145         $this->assertEquals($indicator::get_min_value(), $values[$user1->id][0]);
146         $this->assertEquals($indicator::get_min_value(), $values[$user2->id][0]);
148         $beforecourseeventcreate = time();
149         sleep(1);
151         \logstore_standard\event\unittest_executed::create(
152             array('context' => $coursecontext1, 'userid' => $user1->id))->trigger();
153         $values = $indicator->calculate($sampleids, 'user');
154         $this->assertEquals($indicator::get_max_value(), $values[$user1->id][0]);
155         $this->assertEquals($indicator::get_min_value(), $values[$user2->id][0]);
157         // Now try with course-level samples where user is not available.
158         $sampleids = array($course1->id => $course1->id, $course2->id => $course2->id);
159         $data = array(
160             $course1->id => array(
161                 'context' => $coursecontext1,
162                 'course' => $course1,
163             ),
164             $course2->id => array(
165                 'context' => $coursecontext2,
166                 'course' => $course2,
167             )
168         );
169         $indicator->clear_sample_data();
170         $indicator->add_sample_data($data);
172         // Limited by time to avoid previous logs interfering as other logs
173         // have been generated by the system.
174         $values = $indicator->calculate($sampleids, 'course', $beforecourseeventcreate);
175         $this->assertEquals($indicator::get_max_value(), $values[$course1->id][0]);
176         $this->assertEquals($indicator::get_min_value(), $values[$course2->id][0]);
178         // Test read actions.
179         $course = $this->getDataGenerator()->create_course();
180         $coursecontext = \context_course::instance($course->id);
181         $this->getDataGenerator()->enrol_user($user1->id, $course->id);
183         $indicator = new \core\analytics\indicator\read_actions();
185         $sampleids = array($user1->id => $user1->id, $user2->id => $user2->id);
186         $data = array($user1->id => array(
187             'context' => $coursecontext,
188             'course' => $course,
189             'user' => $user1
190         ));
191         $data[$user2->id] = $data[$user1->id];
192         $data[$user2->id]['user'] = $user2;
193         $indicator->add_sample_data($data);
195         // More or less 4 weeks duration.
196         $startdate = time() - (WEEKSECS * 2);
197         $enddate = time() + (WEEKSECS * 2);
199         $this->setAdminUser();
200         $values = $indicator->calculate($sampleids, 'user');
201         $this->assertNull($values[$user1->id][0]);
202         $this->assertNull($values[$user1->id][1]);
203         $this->assertNull($values[$user1->id][0]);
204         $this->assertNull($values[$user2->id][1]);
206         // Zero score for 0 accesses.
207         $values = $indicator->calculate($sampleids, 'user', $startdate, $enddate);
208         $this->assertEquals($indicator::get_min_value(), $values[$user1->id][0]);
209         $this->assertEquals($indicator::get_min_value(), $values[$user2->id][0]);
211         // 1/3 score for more than 0 accesses.
212         \core\event\course_viewed::create(
213             array('context' => $coursecontext, 'userid' => $user1->id))->trigger();
214         $values = $indicator->calculate($sampleids, 'user', $startdate, $enddate);
215         $this->assertEquals(-0.33, $values[$user1->id][0]);
216         $this->assertEquals($indicator::get_min_value(), $values[$user2->id][0]);
218         // 2/3 score for more than 1 access per week.
219         for ($i = 0; $i < 12; $i++) {
220             \core\event\course_viewed::create(
221                 array('context' => $coursecontext, 'userid' => $user1->id))->trigger();
222         }
223         $values = $indicator->calculate($sampleids, 'user', $startdate, $enddate);
224         $this->assertEquals(0.33, $values[$user1->id][0]);
225         $this->assertEquals($indicator::get_min_value(), $values[$user2->id][0]);
227         // 100% score for tons of accesses during this period (3 logs per access * 4 weeks * 10 accesses).
228         for ($i = 0; $i < (3 * 10 * 4); $i++) {
229             \core\event\course_viewed::create(
230                 array('context' => $coursecontext, 'userid' => $user1->id))->trigger();
231         }
232         $values = $indicator->calculate($sampleids, 'user', $startdate, $enddate);
233         $this->assertEquals($indicator::get_max_value(), $values[$user1->id][0]);
234         $this->assertEquals($indicator::get_min_value(), $values[$user2->id][0]);
235     }