Proyectos de Subversion Moodle

Rev

Rev 11 | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 11 Rev 1441
Línea 14... Línea 14...
14
// You should have received a copy of the GNU General Public License
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/>.
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
Línea 16... Línea 16...
16
 
16
 
Línea -... Línea 17...
-
 
17
namespace core_analytics;
-
 
18
 
17
namespace core_analytics;
19
use core_analytics\tests\mlbackend_helper_trait;
Línea 18... Línea 20...
18
 
20
 
19
defined('MOODLE_INTERNAL') || die();
21
defined('MOODLE_INTERNAL') || die();
20
 
22
 
Línea 29... Línea 31...
29
 * @package   core_analytics
31
 * @package   core_analytics
30
 * @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
32
 * @copyright 2017 David Monllaó {@link http://www.davidmonllao.com}
31
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
32
 * @covers    \core_analytics\manager
34
 * @covers    \core_analytics\manager
33
 */
35
 */
34
class manager_test extends \advanced_testcase {
36
final class manager_test extends \advanced_testcase {
-
 
37
    use mlbackend_helper_trait;
Línea 35... Línea 38...
35
 
38
 
36
    /**
39
    /**
37
     * test_deleted_context
40
     * test_deleted_context
38
     */
41
     */
39
    public function test_deleted_context(): void {
42
    public function test_deleted_context(): void {
Línea -... Línea 43...
-
 
43
        global $DB;
-
 
44
 
-
 
45
        if (!self::is_mlbackend_python_configured()) {
-
 
46
            $this->markTestSkipped('mlbackend_python is not configured.');
40
        global $DB;
47
        }
41
 
48
 
42
        $this->resetAfterTest(true);
49
        $this->resetAfterTest(true);
Línea -... Línea 50...
-
 
50
        $this->setAdminuser();
-
 
51
        set_config('enabled_stores', 'logstore_standard', 'tool_log');
-
 
52
 
-
 
53
        // Create some courses.
43
        $this->setAdminuser();
54
        $this->generate_courses(2, ['visible' => 0]);
44
        set_config('enabled_stores', 'logstore_standard', 'tool_log');
55
        $this->generate_courses(2, ['visible' => 1]);
45
 
56
 
46
        $target = \core_analytics\manager::get_target('test_target_course_level_shortname');
57
        $target = \core_analytics\manager::get_target('test_target_course_level_shortname');
47
        $indicators = array('test_indicator_max', 'test_indicator_min', 'test_indicator_fullname');
58
        $indicators = ['test_indicator_max', 'test_indicator_min', 'test_indicator_fullname'];
Línea 48... Línea 59...
48
        foreach ($indicators as $key => $indicator) {
59
        foreach ($indicators as $key => $indicator) {
49
            $indicators[$key] = \core_analytics\manager::get_indicator($indicator);
60
            $indicators[$key] = \core_analytics\manager::get_indicator($indicator);
Línea 50... Línea -...
50
        }
-
 
51
 
-
 
52
        $model = \core_analytics\model::create($target, $indicators);
-
 
53
        $modelobj = $model->get_model_obj();
-
 
54
 
-
 
55
        $coursepredict1 = $this->getDataGenerator()->create_course(array('visible' => 0));
61
        }
Línea 56... Línea 62...
56
        $coursepredict2 = $this->getDataGenerator()->create_course(array('visible' => 0));
62
 
57
        $coursetrain1 = $this->getDataGenerator()->create_course(array('visible' => 1));
63
        $model = \core_analytics\model::create($target, $indicators);
Línea 58... Línea 64...
58
        $coursetrain2 = $this->getDataGenerator()->create_course(array('visible' => 1));
64
        $modelobj = $model->get_model_obj();
59
 
65
 
60
        $model->enable('\core\analytics\time_splitting\no_splitting');
66
        $model->enable('\core\analytics\time_splitting\no_splitting');
61
 
67
 
62
        $model->train();
68
        $model->train();
Línea 63... Línea 69...
63
        $model->predict();
69
        $model->predict();
Línea 64... Línea 70...
64
 
70
 
65
        // Generate a prediction action to confirm that it is deleted when there is an important update.
71
        // Generate a prediction action to confirm that it is deleted when there is an important update.
-
 
72
        $predictions = $DB->get_records('analytics_predictions');
66
        $predictions = $DB->get_records('analytics_predictions');
73
        $prediction = reset($predictions);
-
 
74
        $prediction = new \core_analytics\prediction($prediction, ['whatever' => 'not used']);
67
        $prediction = reset($predictions);
75
        $prediction->action_executed(\core_analytics\prediction::ACTION_USEFUL, $model->get_target());
Línea 68... Línea 76...
68
        $prediction = new \core_analytics\prediction($prediction, array('whatever' => 'not used'));
76
 
Línea 69... Línea 77...
69
        $prediction->action_executed(\core_analytics\prediction::ACTION_USEFUL, $model->get_target());
77
        $predictioncontextid = $prediction->get_prediction_data()->contextid;
70
 
78
 
-
 
79
        $npredictions = $DB->count_records('analytics_predictions', ['contextid' => $predictioncontextid]);
71
        $predictioncontextid = $prediction->get_prediction_data()->contextid;
80
        $npredictionactions = $DB->count_records(
-
 
81
            'analytics_prediction_actions',
72
 
82
            ['predictionid' => $prediction->get_prediction_data()->id]
-
 
83
        );
73
        $npredictions = $DB->count_records('analytics_predictions', array('contextid' => $predictioncontextid));
84
        $nindicatorcalc = $DB->count_records('analytics_indicator_calc', ['contextid' => $predictioncontextid]);
-
 
85
 
74
        $npredictionactions = $DB->count_records('analytics_prediction_actions',
86
        \core_analytics\manager::cleanup();
-
 
87
 
75
            array('predictionid' => $prediction->get_prediction_data()->id));
88
        // Nothing is incorrectly deleted.
-
 
89
        $this->assertEquals($npredictions, $DB->count_records(
Línea 76... Línea 90...
76
        $nindicatorcalc = $DB->count_records('analytics_indicator_calc', array('contextid' => $predictioncontextid));
90
            'analytics_predictions',
77
 
91
            ['contextid' => $predictioncontextid]
78
        \core_analytics\manager::cleanup();
92
        ));
Línea 79... Línea 93...
79
 
93
        $this->assertEquals($npredictionactions, $DB->count_records(
Línea 80... Línea 94...
80
        // Nothing is incorrectly deleted.
94
            'analytics_prediction_actions',
81
        $this->assertEquals($npredictions, $DB->count_records('analytics_predictions',
95
            ['predictionid' => $prediction->get_prediction_data()->id]
-
 
96
        ));
82
            array('contextid' => $predictioncontextid)));
97
        $this->assertEquals($nindicatorcalc, $DB->count_records(
-
 
98
            'analytics_indicator_calc',
83
        $this->assertEquals($npredictionactions, $DB->count_records('analytics_prediction_actions',
99
            ['contextid' => $predictioncontextid]
Línea 84... Línea 100...
84
            array('predictionid' => $prediction->get_prediction_data()->id)));
100
        ));
85
        $this->assertEquals($nindicatorcalc, $DB->count_records('analytics_indicator_calc',
101
 
86
            array('contextid' => $predictioncontextid)));
102
        // Now we delete a context, the course predictions and prediction actions should be deleted.
Línea 104... Línea 120...
104
     * test_deleted_analysable
120
     * test_deleted_analysable
105
     */
121
     */
106
    public function test_deleted_analysable(): void {
122
    public function test_deleted_analysable(): void {
107
        global $DB;
123
        global $DB;
Línea -... Línea 124...
-
 
124
 
-
 
125
        if (!self::is_mlbackend_python_configured()) {
-
 
126
            $this->markTestSkipped('mlbackend_python is not configured.');
-
 
127
        }
108
 
128
 
109
        $this->resetAfterTest(true);
129
        $this->resetAfterTest(true);
110
        $this->setAdminuser();
130
        $this->setAdminuser();
Línea 111... Línea 131...
111
        set_config('enabled_stores', 'logstore_standard', 'tool_log');
131
        set_config('enabled_stores', 'logstore_standard', 'tool_log');
112
 
132
 
113
        $target = \core_analytics\manager::get_target('test_target_course_level_shortname');
133
        $target = \core_analytics\manager::get_target('test_target_course_level_shortname');
114
        $indicators = array('test_indicator_max', 'test_indicator_min', 'test_indicator_fullname');
134
        $indicators = ['test_indicator_max', 'test_indicator_min', 'test_indicator_fullname'];
115
        foreach ($indicators as $key => $indicator) {
135
        foreach ($indicators as $key => $indicator) {
Línea 116... Línea 136...
116
            $indicators[$key] = \core_analytics\manager::get_indicator($indicator);
136
            $indicators[$key] = \core_analytics\manager::get_indicator($indicator);
117
        }
137
        }
Línea 118... Línea 138...
118
 
138
 
119
        $model = \core_analytics\model::create($target, $indicators);
139
        $model = \core_analytics\model::create($target, $indicators);
120
        $modelobj = $model->get_model_obj();
140
        $modelobj = $model->get_model_obj();
121
 
141
 
Línea 122... Línea 142...
122
        $coursepredict1 = $this->getDataGenerator()->create_course(array('visible' => 0));
142
        $coursepredict1 = $this->getDataGenerator()->create_course(['visible' => 0]);
Línea 123... Línea 143...
123
        $coursepredict2 = $this->getDataGenerator()->create_course(array('visible' => 0));
143
        $coursepredict2 = $this->getDataGenerator()->create_course(['visible' => 0]);
124
        $coursetrain1 = $this->getDataGenerator()->create_course(array('visible' => 1));
144
        $coursetrain1 = $this->getDataGenerator()->create_course(['visible' => 1]);
Línea 137... Línea 157...
137
        $deletedcontext = \context_course::instance($coursepredict1->id);
157
        $deletedcontext = \context_course::instance($coursepredict1->id);
138
        delete_course($coursepredict1, false);
158
        delete_course($coursepredict1, false);
Línea 139... Línea 159...
139
 
159
 
Línea 140... Línea 160...
140
        \core_analytics\manager::cleanup();
160
        \core_analytics\manager::cleanup();
141
 
161
 
142
        $this->assertEmpty($DB->count_records('analytics_predict_samples', array('analysableid' => $coursepredict1->id)));
162
        $this->assertEmpty($DB->count_records('analytics_predict_samples', ['analysableid' => $coursepredict1->id]));
Línea 143... Línea 163...
143
        $this->assertEmpty($DB->count_records('analytics_train_samples', array('analysableid' => $coursepredict1->id)));
163
        $this->assertEmpty($DB->count_records('analytics_train_samples', ['analysableid' => $coursepredict1->id]));
144
        $this->assertEmpty($DB->count_records('analytics_used_analysables', array('analysableid' => $coursepredict1->id)));
164
        $this->assertEmpty($DB->count_records('analytics_used_analysables', ['analysableid' => $coursepredict1->id]));
145
 
165
 
Línea 188... Línea 208...
188
     */
208
     */
189
    public function test_validate_models_declaration(): void {
209
    public function test_validate_models_declaration(): void {
190
        $this->resetAfterTest();
210
        $this->resetAfterTest();
Línea 191... Línea 211...
191
 
211
 
192
        // This is expected to run without an exception.
212
        // This is expected to run without an exception.
193
        $models = $this->load_models_from_fixture_file('no_teaching');
213
        $models = self::load_models_from_fixture_file('no_teaching');
194
        \core_analytics\manager::validate_models_declaration($models);
214
        \core_analytics\manager::validate_models_declaration($models);
Línea 195... Línea 215...
195
    }
215
    }
196
 
216
 
Línea 212... Línea 232...
212
    /**
232
    /**
213
     * Data provider for the {@link self::test_validate_models_declaration_exceptions()}.
233
     * Data provider for the {@link self::test_validate_models_declaration_exceptions()}.
214
     *
234
     *
215
     * @return array of (string)testcase => [(array)models, (string)expected exception message]
235
     * @return array of (string)testcase => [(array)models, (string)expected exception message]
216
     */
236
     */
217
    public function validate_models_declaration_exceptions_provider() {
237
    public static function validate_models_declaration_exceptions_provider(): array {
218
        return [
238
        return [
219
            'missing_target' => [
239
            'missing_target' => [
220
                $this->load_models_from_fixture_file('missing_target'),
240
                self::load_models_from_fixture_file('missing_target'),
221
                'Missing target declaration',
241
                'Missing target declaration',
222
            ],
242
            ],
223
            'invalid_target' => [
243
            'invalid_target' => [
224
                $this->load_models_from_fixture_file('invalid_target'),
244
                self::load_models_from_fixture_file('invalid_target'),
225
                'Invalid target classname',
245
                'Invalid target classname',
226
            ],
246
            ],
227
            'missing_indicators' => [
247
            'missing_indicators' => [
228
                $this->load_models_from_fixture_file('missing_indicators'),
248
                self::load_models_from_fixture_file('missing_indicators'),
229
                'Missing indicators declaration',
249
                'Missing indicators declaration',
230
            ],
250
            ],
231
            'invalid_indicators' => [
251
            'invalid_indicators' => [
232
                $this->load_models_from_fixture_file('invalid_indicators'),
252
                self::load_models_from_fixture_file('invalid_indicators'),
233
                'Invalid indicator classname',
253
                'Invalid indicator classname',
234
            ],
254
            ],
235
            'invalid_time_splitting' => [
255
            'invalid_time_splitting' => [
236
                $this->load_models_from_fixture_file('invalid_time_splitting'),
256
                self::load_models_from_fixture_file('invalid_time_splitting'),
237
                'Invalid time splitting classname',
257
                'Invalid time splitting classname',
238
            ],
258
            ],
239
            'invalid_time_splitting_fq' => [
259
            'invalid_time_splitting_fq' => [
240
                $this->load_models_from_fixture_file('invalid_time_splitting_fq'),
260
                self::load_models_from_fixture_file('invalid_time_splitting_fq'),
241
                'Expecting fully qualified time splitting classname',
261
                'Expecting fully qualified time splitting classname',
242
            ],
262
            ],
243
            'invalid_enabled' => [
263
            'invalid_enabled' => [
244
                $this->load_models_from_fixture_file('invalid_enabled'),
264
                self::load_models_from_fixture_file('invalid_enabled'),
245
                'Cannot enable a model without time splitting method specified',
265
                'Cannot enable a model without time splitting method specified',
246
            ],
266
            ],
247
        ];
267
        ];
248
    }
268
    }
Línea 251... Línea 271...
251
     * Loads models as declared in the given fixture file.
271
     * Loads models as declared in the given fixture file.
252
     *
272
     *
253
     * @param string $filename
273
     * @param string $filename
254
     * @return array
274
     * @return array
255
     */
275
     */
256
    protected function load_models_from_fixture_file(string $filename) {
276
    protected static function load_models_from_fixture_file(string $filename) {
257
        global $CFG;
277
        global $CFG;
Línea 258... Línea 278...
258
 
278
 
Línea 259... Línea 279...
259
        $models = null;
279
        $models = null;
Línea 260... Línea 280...
260
 
280
 
261
        require($CFG->dirroot.'/analytics/tests/fixtures/db_analytics_php/'.$filename.'.php');
281
        require("{$CFG->dirroot}/analytics/tests/fixtures/db_analytics_php/{$filename}.php");
Línea 262... Línea 282...
262
 
282
 
Línea 428... Línea 448...
428
    /**
448
    /**
429
     * Test the implementation of the {@link \core_analytics\manager::model_declaration_identifier()}.
449
     * Test the implementation of the {@link \core_analytics\manager::model_declaration_identifier()}.
430
     */
450
     */
431
    public function test_model_declaration_identifier(): void {
451
    public function test_model_declaration_identifier(): void {
Línea 432... Línea 452...
432
 
452
 
433
        $noteaching1 = $this->load_models_from_fixture_file('no_teaching');
453
        $noteaching1 = self::load_models_from_fixture_file('no_teaching');
434
        $noteaching2 = $this->load_models_from_fixture_file('no_teaching');
454
        $noteaching2 = self::load_models_from_fixture_file('no_teaching');
Línea 435... Línea 455...
435
        $noteaching3 = $this->load_models_from_fixture_file('no_teaching');
455
        $noteaching3 = self::load_models_from_fixture_file('no_teaching');
436
 
456
 
437
        // Same model declaration should always lead to same identifier.
457
        // Same model declaration should always lead to same identifier.
438
        $this->assertEquals(
458
        $this->assertEquals(
Línea 472... Línea 492...
472
     * Tests for the {@link \core_analytics\manager::get_declared_target_and_indicators_instances()}.
492
     * Tests for the {@link \core_analytics\manager::get_declared_target_and_indicators_instances()}.
473
     */
493
     */
474
    public function test_get_declared_target_and_indicators_instances(): void {
494
    public function test_get_declared_target_and_indicators_instances(): void {
475
        $this->resetAfterTest();
495
        $this->resetAfterTest();
Línea 476... Línea 496...
476
 
496
 
Línea 477... Línea 497...
477
        $definition = $this->load_models_from_fixture_file('no_teaching');
497
        $definition = self::load_models_from_fixture_file('no_teaching');
Línea 478... Línea 498...
478
 
498
 
479
        list($target, $indicators) = \core_analytics\manager::get_declared_target_and_indicators_instances($definition[0]);
499
        [$target, $indicators] = \core_analytics\manager::get_declared_target_and_indicators_instances($definition[0]);
480
 
500
 
481
        $this->assertTrue($target instanceof \core_analytics\local\target\base);
501
        $this->assertTrue($target instanceof \core_analytics\local\target\base);