Skip to content

Commit

Permalink
add a unit test for question bank performance, should only be manuall…
Browse files Browse the repository at this point in the history
…y enabled for local testing
  • Loading branch information
dionysius committed Oct 15, 2020
1 parent 981111b commit 0a8d71c
Show file tree
Hide file tree
Showing 3 changed files with 232 additions and 2 deletions.
230 changes: 230 additions & 0 deletions tests/bank_performance_test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
<?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/>.

/**
* Unit tests for the question bank query performance.
*
* @package mod_studentquiz
* @copyright 2020 HSR (http://www.hsr.ch)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

defined('MOODLE_INTERNAL') || die();

global $CFG;
require_once($CFG->dirroot . '/mod/studentquiz/classes/question/bank/studentquiz_bank_view.php');
require_once($CFG->dirroot . '/mod/studentquiz/reportlib.php');
require_once($CFG->dirroot . '/lib/questionlib.php');
require_once($CFG->dirroot . '/question/editlib.php');

/**
* Unit tests for the question bank query performance.
*
* The question bank query to get all the questions is pretty large and modular. This test wants to provide
* some visibility to the performance of that query for a set amount of entries in the database.
*
* To truly test the question bank query performance, there should be:
* - Some instances of studentquizzes
* - Many questions per instance
* - A few comments per question
* - Some attempts per question (TODO)
* - Some ratings per question
* - Some filter applied (TODO)
*
* Right now, there are no hard requirements other than "usuable" even for large moodle sites which heavily use
* StudentQuiz. This test can only help comparing the query duration to previous versions and in relation to the
* dataset size. As many performance tests, they rely heavily on the hardware and environment they're run on.
*
* @package mod_studentquiz
* @copyright 2020 HSR (http://www.hsr.ch)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_studentquiz_bank_performance_test extends advanced_testcase {
/**
* @var question generator
*/
private $questiongenerator;
/**
* @var studentquiz generator
*/
private $studentquizgenerator;

/**
* Setup testing scenario
* @throws coding_exception
*/
protected function setUp() {
$this->questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
$this->studentquizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_studentquiz');
}

/**
* Run questionbank.
*
* @param array $result with the last studentquiz and its relations
* @return \mod_studentquiz\question\bank\studentquiz_bank_view
* @throws mod_studentquiz_view_exception
* @throws moodle_exception
*/
public function run_questionbank($result) {
global $PAGE;
$PAGE->set_url(new moodle_url('/mod/studentquiz/view.php', array('cmid' => $result['cm']->id)));
$PAGE->set_context($result['ctx']);
// Hard coded.
$pagevars = array(
'recurse' => true,
'cat' => $result['cat']->id . ',' . $result['ctx']->id,
'showall' => 1,
'showallprinted' => 0,
);

$report = new mod_studentquiz_report($result['cm']->id);
$questionbank = new \mod_studentquiz\question\bank\studentquiz_bank_view(
new question_edit_contexts(context_module::instance($result['cm']->id)),
new moodle_url('/mod/studentquiz/view.php', array('cmid' => $result['cm']->id)),
$result['course'], $result['cm'], $result['studentquiz'], $pagevars, $report);
return $questionbank;
}

/**
* Create a specific amount of instances in a new course.
*
* @param int $count of instances to create
* @return array $result with the last studentquiz and its relations
*/
protected function create_instances_testset($count) {
global $DB;
$result = array();

// Create a course.
$course = $this->getDataGenerator()->create_course();
$result['course'] = $course;
$studentrole = $DB->get_record('role', array('shortname' => 'student'));

// In that course create $count studentquiz instances.
for ($i = 0; $i < $count; $i++) {
$studentquiz = $this->getDataGenerator()->create_module('studentquiz',
array('course' => $course->id), array('anonymrank' => true)
);
$result['studentquiz'] = $studentquiz;

// Get the question category for that studentquiz context
$cm = get_coursemodule_from_instance('studentquiz', $studentquiz->id);
$result['cm'] = $cm;
$ctx = context_module::instance($cm->id);
$result['ctx'] = $ctx;
$cat = question_get_default_category($ctx->id);
$result['cat'] = $cat;

// Each instance has 20 students which are enrolled to the course.
$students = array();
for ($s = 0; $s < 20; $s++) {
$user = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id);
$students[] = $user;
}

// Each student makes 20 questions.
$questions = array();
foreach ($students as $student) {
for ($q = 1; $q <= 20; $q++) {
$questions[] = $this->questiongenerator->create_question('description', null,
array('name' => 'perf'.$q, 'category' => $cat->id, 'createdby' => $student->id)
);
}
}

// The first 5 students contribute a comment to all questions
for ($s = 0; $s <5; $s++) {
foreach ($questions as $question) {
$this->studentquizgenerator->create_comment(array(
'questionid' => $question->id,
'userid' => $students[$s]->id,
));
}
}

// All students rate each question
foreach ($students as $student) {
foreach ($questions as $question) {
$this->studentquizgenerator->create_rate(array(
'questionid' => $question->id,
'userid' => $students[$s]->id,
'rate' => 5,
));
}
}
}

return $result;
}

/**
* Test questionbank empty filter
*/
public function test_questionbank_empty_filter() {
$this->resetAfterTest(true);

// If we don't activate the lower two, it doesn't make sense to enable this one either.
// Adding 10 instances takes a few minutes, this should not be enabled in CI.
// Adding 100 instances takes a huuuge amount of time (hours) until ready.
// Uncomment these lines to run the tests with phpunit.
// $this->create_instance_measured(1);
// $this->create_instance_measured(10);
// $this->create_instance_measured(100);
}

/**
* Create a specific amount of instances in a new course and output how long it took to display the
* question bank
*
* @param int $count of instances to create
*/
protected function create_instance_measured($count) {
fwrite(STDERR, "TEST_PERF: create $count instances\n");

$result = $this->create_instances_testset($count);
$questionbank = $this->run_questionbank($result);

fwrite(STDERR, "TEST_PERF: initialization complete\n");

$start = microtime(true);
$this->displayqb($questionbank, $result);
$end = microtime(true);
$diff = $end - $start;
fwrite(STDERR, "TEST_PERF: displaying question bank took $diff s\n");

$this->assertEquals(400, count($questionbank->get_questions()));
}

/**
* Display question bank
* @param mod_studentquiz\question\bank\studentquiz_bank_view $questionbank
* @param array $result with the last studentquiz and its relations
* @param int $qpage
* @param int $qperpage
* @param int $recurse
* @param int $showhidden
* @param int $qbshowtext
* @return string
*/
protected function displayqb($questionbank, $result, $qpage = 0, $qperpage = 20, $recurse = 1, $showhidden = 0, $qbshowtext = 0) {
$cat = $result['cat']->id . "," . $result['ctx']->id;
$questionbank->display('questions', $qpage, $qperpage,
$cat, $recurse, $showhidden,
$qbshowtext);
}
}
2 changes: 1 addition & 1 deletion tests/generator/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public function create_rate($record = null) {

$this->ratecount++;

$record['id'] = $DB->insert_record('studentquiz_comment', $record);
$record['id'] = $DB->insert_record('studentquiz_rate', $record);
return (object) $record;
}
}
2 changes: 1 addition & 1 deletion tests/studentquiz_bank_view_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class mod_studentquiz_bank_view_test extends advanced_testcase {
*/
private $questiongenerator;
/**
* @var stundetquiz generator
* @var studentquiz generator
*/
private $studentquizgenerator;

Expand Down

0 comments on commit 0a8d71c

Please sign in to comment.