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 core analysers. 19 * 20 * @package core 21 * @category test 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 */ 25 26defined('MOODLE_INTERNAL') || die(); 27 28require_once(__DIR__ . '/../../analytics/tests/fixtures/test_target_course_level_shortname.php'); 29require_once(__DIR__ . '/../../analytics/tests/fixtures/test_target_shortname.php'); 30require_once(__DIR__ . '/../../lib/enrollib.php'); 31 32/** 33 * Unit tests for core analysers. 34 * 35 * @package core 36 * @category test 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 */ 40class core_analytics_analysers_testcase extends advanced_testcase { 41 42 /** 43 * test_courses_analyser 44 * 45 * @return void 46 */ 47 public function test_courses_analyser() { 48 $this->resetAfterTest(true); 49 50 $course1 = $this->getDataGenerator()->create_course(); 51 $coursecontext = \context_course::instance($course1->id); 52 53 $target = new test_target_shortname(); 54 $analyser = new \core\analytics\analyser\courses(1, $target, [], [], []); 55 $analysable = new \core_analytics\course($course1); 56 57 $this->assertInstanceOf('\core_analytics\course', $analyser->get_sample_analysable($course1->id)); 58 59 $this->assertInstanceOf('\context_course', $analyser->sample_access_context($course1->id)); 60 61 // Just 1 sample per course. 62 $class = new ReflectionClass('\core\analytics\analyser\courses'); 63 $method = $class->getMethod('get_all_samples'); 64 $method->setAccessible(true); 65 list($sampleids, $samplesdata) = $method->invoke($analyser, $analysable); 66 $this->assertCount(1, $sampleids); 67 $sampleid = reset($sampleids); 68 $this->assertEquals($course1->id, $sampleid); 69 $this->assertEquals($course1->fullname, $samplesdata[$sampleid]['course']->fullname); 70 $this->assertEquals($coursecontext, $samplesdata[$sampleid]['context']); 71 72 // To compare it later. 73 $prevsampledata = $samplesdata[$sampleid]; 74 list($sampleids, $samplesdata) = $analyser->get_samples(array($sampleid)); 75 $this->assertEquals($prevsampledata['context'], $samplesdata[$sampleid]['context']); 76 $this->assertEquals($prevsampledata['course']->shortname, $samplesdata[$sampleid]['course']->shortname); 77 78 // Context restriction. 79 $category1 = $this->getDataGenerator()->create_category(); 80 $category1context = \context_coursecat::instance($category1->id); 81 $category2 = $this->getDataGenerator()->create_category(); 82 $category2context = \context_coursecat::instance($category2->id); 83 $course2 = $this->getDataGenerator()->create_course(['category' => $category1->id]); 84 $course3 = $this->getDataGenerator()->create_course(['category' => $category2->id]); 85 $this->assertCount(2, $analyser->get_analysables_iterator(false, [$category1context, $category2context])); 86 87 } 88 89 /** 90 * test_site_courses_analyser 91 * 92 * @return void 93 */ 94 public function test_site_courses_analyser() { 95 $this->resetAfterTest(true); 96 97 $course1 = $this->getDataGenerator()->create_course(); 98 $course2 = $this->getDataGenerator()->create_course(); 99 $course3 = $this->getDataGenerator()->create_course(); 100 $course1context = \context_course::instance($course1->id); 101 102 $target = new test_target_shortname(); 103 $analyser = new \core\analytics\analyser\site_courses(1, $target, [], [], []); 104 $analysable = new \core_analytics\site(); 105 106 $this->assertInstanceOf('\core_analytics\site', $analyser->get_sample_analysable($course1->id)); 107 $this->assertInstanceOf('\core_analytics\site', $analyser->get_sample_analysable($course2->id)); 108 109 $this->assertInstanceOf('\context_system', $analyser->sample_access_context($course1->id)); 110 $this->assertInstanceOf('\context_system', $analyser->sample_access_context($course3->id)); 111 112 $class = new ReflectionClass('\core\analytics\analyser\site_courses'); 113 $method = $class->getMethod('get_all_samples'); 114 $method->setAccessible(true); 115 list($sampleids, $samplesdata) = $method->invoke($analyser, $analysable); 116 $this->assertCount(3, $sampleids); 117 118 // Use course1 it does not really matter. 119 $this->assertArrayHasKey($course1->id, $sampleids); 120 $sampleid = $course1->id; 121 $this->assertEquals($course1->id, $sampleid); 122 $this->assertEquals($course1->fullname, $samplesdata[$sampleid]['course']->fullname); 123 $this->assertEquals($course1context, $samplesdata[$sampleid]['context']); 124 125 // To compare it later. 126 $prevsampledata = $samplesdata[$sampleid]; 127 list($sampleids, $samplesdata) = $analyser->get_samples(array($sampleid)); 128 $this->assertEquals($prevsampledata['context'], $samplesdata[$sampleid]['context']); 129 $this->assertEquals($prevsampledata['course']->shortname, $samplesdata[$sampleid]['course']->shortname); 130 } 131 132 /** 133 * test_student_enrolments_analyser 134 * 135 * @return void 136 */ 137 public function test_student_enrolments_analyser() { 138 global $DB; 139 140 $this->resetAfterTest(true); 141 142 $course1 = $this->getDataGenerator()->create_course(); 143 $course1context = \context_course::instance($course1->id); 144 145 $user1 = $this->getDataGenerator()->create_user(); 146 $user2 = $this->getDataGenerator()->create_user(); 147 $user3 = $this->getDataGenerator()->create_user(); 148 149 // Checking that suspended users are also included. 150 $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'student'); 151 $this->getDataGenerator()->enrol_user($user2->id, $course1->id, 'student', 'manual', 0, 0, ENROL_USER_SUSPENDED); 152 $this->getDataGenerator()->enrol_user($user3->id, $course1->id, 'editingteacher'); 153 $enrol = $DB->get_record('enrol', array('courseid' => $course1->id, 'enrol' => 'manual')); 154 $ue1 = $DB->get_record('user_enrolments', array('userid' => $user1->id, 'enrolid' => $enrol->id)); 155 $ue2 = $DB->get_record('user_enrolments', array('userid' => $user2->id, 'enrolid' => $enrol->id)); 156 157 $target = new test_target_shortname(); 158 $analyser = new \core\analytics\analyser\student_enrolments(1, $target, [], [], []); 159 $analysable = new \core_analytics\course($course1); 160 161 $this->assertInstanceOf('\core_analytics\course', $analyser->get_sample_analysable($ue1->id)); 162 $this->assertInstanceOf('\context_course', $analyser->sample_access_context($ue1->id)); 163 164 $class = new ReflectionClass('\core\analytics\analyser\student_enrolments'); 165 $method = $class->getMethod('get_all_samples'); 166 $method->setAccessible(true); 167 list($sampleids, $samplesdata) = $method->invoke($analyser, $analysable); 168 // Only students. 169 $this->assertCount(2, $sampleids); 170 171 $this->assertArrayHasKey($ue1->id, $sampleids); 172 $this->assertArrayHasKey($ue2->id, $sampleids); 173 174 // Shouldn't matter which one we select. 175 $sampleid = $ue1->id; 176 $this->assertEquals($ue1, $samplesdata[$sampleid]['user_enrolments']); 177 $this->assertEquals($course1->fullname, $samplesdata[$sampleid]['course']->fullname); 178 $this->assertEquals($course1context, $samplesdata[$sampleid]['context']); 179 $this->assertEquals($user1->firstname, $samplesdata[$sampleid]['user']->firstname); 180 181 // To compare it later. 182 $prevsampledata = $samplesdata[$sampleid]; 183 list($sampleids, $samplesdata) = $analyser->get_samples(array($sampleid)); 184 $this->assertEquals($prevsampledata['user_enrolments'], $samplesdata[$sampleid]['user_enrolments']); 185 $this->assertEquals($prevsampledata['context'], $samplesdata[$sampleid]['context']); 186 $this->assertEquals($prevsampledata['course']->shortname, $samplesdata[$sampleid]['course']->shortname); 187 $this->assertEquals($prevsampledata['user']->firstname, $samplesdata[$sampleid]['user']->firstname); 188 189 // Context restriction. 190 $category1 = $this->getDataGenerator()->create_category(); 191 $category1context = \context_coursecat::instance($category1->id); 192 $category2 = $this->getDataGenerator()->create_category(); 193 $category2context = \context_coursecat::instance($category2->id); 194 $course2 = $this->getDataGenerator()->create_course(['category' => $category1->id]); 195 $course3 = $this->getDataGenerator()->create_course(['category' => $category2->id]); 196 $this->assertCount(2, $analyser->get_analysables_iterator(false, [$category1context, $category2context])); 197 } 198 199 /** 200 * test_get_analysables_iterator description 201 * 202 * @return null 203 */ 204 public function test_get_analysables_iterator() { 205 global $DB; 206 207 $this->resetAfterTest(true); 208 209 $courses = array(); 210 for ($i = 0; $i < 2; $i++) { 211 $course = $this->getDataGenerator()->create_course(); 212 $analysable = new \core_analytics\course($course); 213 $courses[$analysable->get_id()] = $course; 214 } 215 216 // Check that the analysis performs as expected. 217 $modelid = 1; 218 $includetarget = false; 219 220 $target = new test_target_course_level_shortname(); 221 $analyser = new \core\analytics\analyser\courses($modelid, $target, [], [], []); 222 223 $result = new \core_analytics\local\analysis\result_array($modelid, $includetarget, []); 224 $analysis = new \core_analytics\analysis($analyser, $includetarget, $result); 225 $analysis->run(); 226 $params = array('modelid' => $modelid, 'action' => 'prediction'); 227 $this->assertEquals(2, $DB->count_records('analytics_used_analysables', $params)); 228 229 // Check that the previous records do not conflict with the includetarget == false ones. 230 $includetarget = true; 231 232 $target = new test_target_course_level_shortname(); 233 $analyser = new \core\analytics\analyser\courses($modelid, $target, [], [], []); 234 235 $result = new \core_analytics\local\analysis\result_array($modelid, $includetarget, []); 236 $analysis = new \core_analytics\analysis($analyser, $includetarget, $result); 237 $analysis->run(); 238 $params = array('modelid' => $modelid, 'action' => 'prediction'); 239 $this->assertEquals(2, $DB->count_records('analytics_used_analysables', $params)); 240 $params = array('modelid' => $modelid, 'action' => 'training'); 241 $this->assertEquals(2, $DB->count_records('analytics_used_analysables', $params)); 242 $params = array('modelid' => $modelid); 243 $this->assertEquals(4, $DB->count_records('analytics_used_analysables', $params)); 244 245 // Check that other models' records do not conflict with previous records. 246 $prevmodelid = 1; 247 $modelid = 2; 248 $includetarget = false; 249 250 $target = new test_target_course_level_shortname(); 251 $analyser = new \core\analytics\analyser\courses($modelid, $target, [], [], []); 252 253 $result = new \core_analytics\local\analysis\result_array($modelid, $includetarget, []); 254 $analysis = new \core_analytics\analysis($analyser, $includetarget, $result); 255 $analysis->run(); 256 $params = array('modelid' => $prevmodelid); 257 $this->assertEquals(4, $DB->count_records('analytics_used_analysables', $params)); 258 $params = array('modelid' => $modelid, 'action' => 'prediction'); 259 $this->assertEquals(2, $DB->count_records('analytics_used_analysables', $params)); 260 $this->assertEquals(6, $DB->count_records('analytics_used_analysables')); 261 262 $includetarget = true; 263 264 $target = new test_target_course_level_shortname(); 265 $analyser = new \core\analytics\analyser\courses($modelid, $target, [], [], []); 266 267 $result = new \core_analytics\local\analysis\result_array($modelid, $includetarget, []); 268 $analysis = new \core_analytics\analysis($analyser, $includetarget, $result); 269 $analysis->run(); 270 $params = array('modelid' => $prevmodelid); 271 $this->assertEquals(4, $DB->count_records('analytics_used_analysables', $params)); 272 $params = array('modelid' => $modelid, 'action' => 'training'); 273 $this->assertEquals(2, $DB->count_records('analytics_used_analysables', $params)); 274 $this->assertEquals(8, $DB->count_records('analytics_used_analysables')); 275 } 276} 277