Differences Between: [Versions 400 and 403] [Versions 401 and 403] [Versions 402 and 403]
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 declare(strict_types=1); 18 19 use core_reportbuilder\manager; 20 use core_reportbuilder\local\helpers\aggregation; 21 use core_reportbuilder\local\helpers\report; 22 use core_reportbuilder\local\helpers\user_filter_manager; 23 use core_reportbuilder\table\custom_report_table_view; 24 25 /** 26 * Helper base class for reportbuilder unit tests 27 * 28 * @package core_reportbuilder 29 * @copyright 2021 Paul Holden <paulh@moodle.com> 30 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 31 */ 32 abstract class core_reportbuilder_testcase extends advanced_testcase { 33 34 /** 35 * Retrieve content for given report as array of report data 36 * 37 * @param int $reportid 38 * @param int $pagesize 39 * @param array $filtervalues 40 * @return array[] 41 */ 42 protected function get_custom_report_content(int $reportid, int $pagesize = 30, array $filtervalues = []): array { 43 $records = []; 44 45 // Apply filter values. 46 user_filter_manager::set($reportid, $filtervalues); 47 48 // Create table instance. 49 $table = custom_report_table_view::create($reportid); 50 $table->setup(); 51 $table->query_db($pagesize, false); 52 53 // Extract raw data. 54 foreach ($table->rawdata as $record) { 55 $records[] = $table->format_row($record); 56 } 57 58 $table->close_recordset(); 59 60 return $records; 61 } 62 63 /** 64 * Stress test a report source by iterating over all it's columns, enabling sorting where possible and asserting we can 65 * create a report for each 66 * 67 * @param string $source 68 */ 69 protected function datasource_stress_test_columns(string $source): void { 70 71 /** @var core_reportbuilder_generator $generator */ 72 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 73 74 $report = $generator->create_report(['name' => 'Stress columns', 'source' => $source, 'default' => 0]); 75 $instance = manager::get_report_from_persistent($report); 76 77 // Iterate over each available column, ensure each works correctly independent of any others. 78 foreach ($instance->get_columns() as $columnidentifier => $columninstance) { 79 $column = report::add_report_column($report->get('id'), $columnidentifier); 80 81 // Enable sorting of the column where possible. 82 if ($columninstance->get_is_sortable()) { 83 report::toggle_report_column_sorting($report->get('id'), $column->get('id'), true, SORT_DESC); 84 } 85 86 // We are only asserting the report returns content without errors, not the content itself. 87 try { 88 $content = $this->get_custom_report_content($report->get('id')); 89 $this->assertNotEmpty($content); 90 91 // Ensure appropriate debugging was triggered for deprecated column. 92 if ($columninstance->get_is_deprecated()) { 93 $this->assertDebuggingCalled(null, DEBUG_DEVELOPER); 94 } 95 } catch (Throwable $exception) { 96 $this->fail("Error for column '{$columnidentifier}': " . $exception->getMessage()); 97 } 98 99 report::delete_report_column($report->get('id'), $column->get('id')); 100 } 101 } 102 103 /** 104 * Stress test a report source by iterating over all columns and asserting we can create a report while aggregating each 105 * 106 * @param string $source 107 */ 108 protected function datasource_stress_test_columns_aggregation(string $source): void { 109 110 /** @var core_reportbuilder_generator $generator */ 111 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 112 113 $report = $generator->create_report(['name' => 'Stress aggregation', 'source' => $source, 'default' => 0]); 114 $instance = manager::get_report_from_persistent($report); 115 116 // Add every column. 117 $columndeprecatedcount = 0; 118 foreach ($instance->get_columns() as $columnidentifier => $column) { 119 $columndeprecatedcount += (int) $column->get_is_deprecated(); 120 report::add_report_column($report->get('id'), $columnidentifier); 121 } 122 123 // Now iterate over each column, and apply all suitable aggregation types. 124 $columns = $instance->get_active_columns(); 125 $this->assertDebuggingCalledCount($columndeprecatedcount, null, 126 array_fill(0, $columndeprecatedcount, DEBUG_DEVELOPER)); 127 foreach ($columns as $column) { 128 $aggregations = aggregation::get_column_aggregations($column->get_type(), $column->get_disabled_aggregation()); 129 foreach (array_keys($aggregations) as $aggregation) { 130 $column->get_persistent()->set('aggregation', $aggregation)->update(); 131 132 // We are only asserting the report returns content without errors, not the content itself. 133 try { 134 $content = $this->get_custom_report_content($report->get('id')); 135 $this->assertNotEmpty($content); 136 137 // Ensure appropriate debugging was triggered for deprecated columns. 138 $this->assertDebuggingCalledCount($columndeprecatedcount, null, 139 array_fill(0, $columndeprecatedcount, DEBUG_DEVELOPER)); 140 } catch (Throwable $exception) { 141 $this->fail("Error for column '{$column->get_unique_identifier()}' with aggregation '{$aggregation}': " . 142 $exception->getMessage()); 143 } 144 } 145 146 // Reset the column aggregation. 147 $column->get_persistent()->set('aggregation', null)->update(); 148 } 149 } 150 151 /** 152 * Stress test a report source by iterating over all it's conditions and asserting we can create a report using each 153 * 154 * @param string $source 155 * @param string $columnidentifier Should be a simple column, with as few fields and joins as possible, ideally selected 156 * from the base table itself 157 */ 158 protected function datasource_stress_test_conditions(string $source, string $columnidentifier): void { 159 160 /** @var core_reportbuilder_generator $generator */ 161 $generator = $this->getDataGenerator()->get_plugin_generator('core_reportbuilder'); 162 163 $report = $generator->create_report(['name' => 'Stress conditions', 'source' => $source, 'default' => 0]); 164 $instance = manager::get_report_from_persistent($report); 165 166 // Add single column only (to ensure no conditions have reliance on any columns). 167 report::add_report_column($report->get('id'), $columnidentifier); 168 169 // Iterate over each available condition, ensure each works correctly independent of any others. 170 $conditionidentifiers = array_keys($instance->get_conditions()); 171 foreach ($conditionidentifiers as $conditionidentifier) { 172 $condition = report::add_report_condition($report->get('id'), $conditionidentifier); 173 $conditioninstance = $instance->get_condition($condition->get('uniqueidentifier')); 174 175 /** @var \core_reportbuilder\local\filters\base $conditionclass */ 176 $conditionclass = $conditioninstance->get_filter_class(); 177 178 // Set report condition values in order to activate it. 179 $conditionvalues = $conditionclass::create($conditioninstance)->get_sample_values(); 180 if (empty($conditionvalues)) { 181 debugging("Missing sample values from filter '{$conditionclass}'", DEBUG_DEVELOPER); 182 } 183 $instance->set_condition_values($conditionvalues); 184 185 // We are only asserting the report returns content without errors, not the content itself. 186 try { 187 $content = $this->get_custom_report_content($report->get('id')); 188 $this->assertIsArray($content); 189 190 // Ensure appropriate debugging was triggered for deprecated condition. 191 if ($conditioninstance->get_is_deprecated()) { 192 $this->assertDebuggingCalled(null, DEBUG_DEVELOPER); 193 } 194 } catch (Throwable $exception) { 195 $this->fail("Error for condition '{$conditionidentifier}': " . $exception->getMessage()); 196 } 197 198 report::delete_report_condition($report->get('id'), $condition->get('id')); 199 } 200 } 201 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body