mirror of
https://github.com/moodle/moodle.git
synced 2025-08-05 00:46:50 +02:00

Implement stress tester methods for iterating over report columns, aggregation and conditions. Assert that each works correctly in isolation, and when used in conjunction with other columns.
178 lines
7.7 KiB
PHP
178 lines
7.7 KiB
PHP
<?php
|
|
// This file is part of Moodle - http://moodle.org/
|
|
//
|
|
// Moodle is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Moodle is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
declare(strict_types=1);
|
|
|
|
use core_reportbuilder\manager;
|
|
use core_reportbuilder\local\helpers\aggregation;
|
|
use core_reportbuilder\local\helpers\report;
|
|
use core_reportbuilder\local\helpers\user_filter_manager;
|
|
use core_reportbuilder\table\custom_report_table_view;
|
|
|
|
/**
|
|
* Helper base class for reportbuilder unit tests
|
|
*
|
|
* @package core_reportbuilder
|
|
* @copyright 2021 Paul Holden <paulh@moodle.com>
|
|
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
*/
|
|
abstract class core_reportbuilder_testcase extends advanced_testcase {
|
|
|
|
/**
|
|
* Retrieve content for given report as array of report data
|
|
*
|
|
* @param int $reportid
|
|
* @param int $pagesize
|
|
* @param array $filtervalues
|
|
* @return array[]
|
|
*/
|
|
protected function get_custom_report_content(int $reportid, int $pagesize = 30, array $filtervalues = []): array {
|
|
$records = [];
|
|
|
|
// Apply filter values.
|
|
user_filter_manager::set($reportid, $filtervalues);
|
|
|
|
// Create table instance.
|
|
$table = custom_report_table_view::create($reportid);
|
|
$table->setup();
|
|
$table->query_db($pagesize, false);
|
|
|
|
// Extract raw data.
|
|
foreach ($table->rawdata as $record) {
|
|
$records[] = $table->format_row($record);
|
|
}
|
|
|
|
$table->close_recordset();
|
|
|
|
return $records;
|
|
}
|
|
|
|
/**
|
|
* Stress test a report source by iterating over all it's columns and asserting we can create a report for each
|
|
*
|
|
* @param string $source
|
|
*/
|
|
protected function datasource_stress_test_columns(string $source): void {
|
|
|
|
/** @var core_reportbuilder_generator $generator */
|
|
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
|
|
|
$report = $generator->create_report(['name' => 'Stress columns', 'source' => $source, 'default' => 0]);
|
|
$instance = manager::get_report_from_persistent($report);
|
|
|
|
// Iterate over each available column, ensure each works correctly independent of any others.
|
|
$columnidentifiers = array_keys($instance->get_columns());
|
|
foreach ($columnidentifiers as $columnidentifier) {
|
|
$column = report::add_report_column($report->get('id'), $columnidentifier);
|
|
|
|
// We are only asserting the report returns content without errors, not the content itself.
|
|
try {
|
|
$content = $this->get_custom_report_content($report->get('id'));
|
|
$this->assertNotEmpty($content);
|
|
} catch (Throwable $exception) {
|
|
$this->fail("Error for column '{$columnidentifier}': " . $exception->getMessage());
|
|
}
|
|
|
|
report::delete_report_column($report->get('id'), $column->get('id'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Stress test a report source by iterating over all columns and asserting we can create a report while aggregating each
|
|
*
|
|
* @param string $source
|
|
*/
|
|
protected function datasource_stress_test_columns_aggregation(string $source): void {
|
|
|
|
/** @var core_reportbuilder_generator $generator */
|
|
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
|
|
|
$report = $generator->create_report(['name' => 'Stress aggregation', 'source' => $source, 'default' => 0]);
|
|
$instance = manager::get_report_from_persistent($report);
|
|
|
|
// Add every column.
|
|
$columnidentifiers = array_keys($instance->get_columns());
|
|
foreach ($columnidentifiers as $columnidentifier) {
|
|
report::add_report_column($report->get('id'), $columnidentifier);
|
|
}
|
|
|
|
// Now iterate over each column, and apply all suitable aggregation types.
|
|
foreach ($instance->get_active_columns() as $column) {
|
|
$aggregations = aggregation::get_column_aggregations($column->get_type(), $column->get_disabled_aggregation());
|
|
foreach (array_keys($aggregations) as $aggregation) {
|
|
$column->get_persistent()->set('aggregation', $aggregation)->update();
|
|
|
|
// We are only asserting the report returns content without errors, not the content itself.
|
|
try {
|
|
$content = $this->get_custom_report_content($report->get('id'));
|
|
$this->assertNotEmpty($content);
|
|
} catch (Throwable $exception) {
|
|
$this->fail("Error for column '{$column->get_unique_identifier()}' with aggregation '{$aggregation}': " .
|
|
$exception->getMessage());
|
|
}
|
|
}
|
|
|
|
// Reset the column aggregation.
|
|
$column->get_persistent()->set('aggregation', null)->update();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Stress test a report source by iterating over all it's conditions and asserting we can create a report using each
|
|
*
|
|
* @param string $source
|
|
* @param string $columnidentifier Should be a simple column, with as few fields and joins as possible, ideally selected
|
|
* from the base table itself
|
|
*/
|
|
protected function datasource_stress_test_conditions(string $source, string $columnidentifier): void {
|
|
|
|
/** @var core_reportbuilder_generator $generator */
|
|
$generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder');
|
|
|
|
$report = $generator->create_report(['name' => 'Stress conditions', 'source' => $source, 'default' => 0]);
|
|
$instance = manager::get_report_from_persistent($report);
|
|
|
|
// Add single column only (to ensure no conditions have reliance on any columns).
|
|
report::add_report_column($report->get('id'), $columnidentifier);
|
|
|
|
// Iterate over each available condition, ensure each works correctly independent of any others.
|
|
$conditionidentifiers = array_keys($instance->get_conditions());
|
|
foreach ($conditionidentifiers as $conditionidentifier) {
|
|
$condition = report::add_report_condition($report->get('id'), $conditionidentifier);
|
|
$conditioninstance = $instance->get_condition($condition->get('uniqueidentifier'));
|
|
|
|
/** @var \core_reportbuilder\local\filters\base $conditionclass */
|
|
$conditionclass = $conditioninstance->get_filter_class();
|
|
|
|
// Set report condition values in order to activate it.
|
|
$conditionvalues = $conditionclass::create($conditioninstance)->get_sample_values();
|
|
if (empty($conditionvalues)) {
|
|
debugging("Missing sample values from filter '{$conditionclass}'", DEBUG_DEVELOPER);
|
|
}
|
|
$instance->set_condition_values($conditionvalues);
|
|
|
|
// We are only asserting the report returns content without errors, not the content itself.
|
|
try {
|
|
$content = $this->get_custom_report_content($report->get('id'));
|
|
$this->assertIsArray($content);
|
|
} catch (Throwable $exception) {
|
|
$this->fail("Error for condition '{$conditionidentifier}': " . $exception->getMessage());
|
|
}
|
|
|
|
report::delete_report_condition($report->get('id'), $condition->get('id'));
|
|
}
|
|
}
|
|
}
|