Skip to content

Commit

Permalink
MDL-38582 testing: Let any component have a data generator.
Browse files Browse the repository at this point in the history
Plus a simple core_question generator to test the concept.
  • Loading branch information
timhunt committed Mar 22, 2013
1 parent 373a8e0 commit ba203de
Show file tree
Hide file tree
Showing 8 changed files with 239 additions and 40 deletions.
13 changes: 1 addition & 12 deletions lib/testing/generator/block_generator.php
Expand Up @@ -34,21 +34,10 @@
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class testing_block_generator {
/** @var testing_data_generator */
protected $datagenerator;

abstract class testing_block_generator extends component_generator_base {
/** @var number of created instances */
protected $instancecount = 0;

/**
* Dumb constructor to throw the deprecated notification
* @param testing_data_generator $datagenerator
*/
public function __construct(testing_data_generator $datagenerator) {
$this->datagenerator = $datagenerator;
}

/**
* To be called from data reset code only,
* do not use in tests.
Expand Down
59 changes: 59 additions & 0 deletions lib/testing/generator/component_generator_base.php
@@ -0,0 +1,59 @@
<?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/>.

/**
* Component generator base class.
*
* @package core
* @category test
* @copyright 2013 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/


/**
* Component generator base class.
*
* Extend in path/to/component/tests/generator/lib.php as
* class type_plugin_generator extends component_generator_base
* Note that there are more specific classes to extend for mods and blocks.
*
* @copyright 2013 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class component_generator_base {

/**
* @var testing_data_generator
*/
protected $datagenerator;

/**
* Constructor.
* @param testing_data_generator $datagenerator
*/
public function __construct(testing_data_generator $datagenerator) {
$this->datagenerator = $datagenerator;
}

/**
* To be called from data reset code only,
* do not use in tests.
* @return void
*/
public function reset() {
}
}
59 changes: 45 additions & 14 deletions lib/testing/generator/data_generator.php
Expand Up @@ -101,29 +101,40 @@ public function reset() {
}

/**
* Return generator for given plugin
* @param string $component
* @return mixed plugin data generator
* Return generator for given plugin or component.
* @param string $component the component name, e.g. 'mod_forum' or 'core_question'.
* @return component_generator_base or rather an instance of the appropriate subclass.
*/
public function get_plugin_generator($component) {
list($type, $plugin) = normalize_component($component);
$cleancomponent = $type . '_' . $plugin;
if ($cleancomponent != $component) {
debugging("Please specify the component you want a generator for as " .
"{$cleancomponent}, not {$component}.", DEBUG_DEVELOPER);
$component = $cleancomponent;
}

if (isset($this->generators[$component])) {
return $this->generators[$component];
}

if ($type !== 'mod' and $type !== 'block') {
throw new coding_exception("Plugin type $type does not support generators yet");
$dir = get_component_directory($component);
$lib = $dir . '/tests/generator/lib.php';
if (!$dir || !is_readable($lib)) {
throw new coding_exception("Component {$component} does not support " .
"generators yet. Missing tests/generator/lib.php.");
}

$dir = get_plugin_directory($type, $plugin);
include_once($lib);
$classname = $component . '_generator';

if (!isset($this->generators[$type.'_'.$plugin])) {
$lib = "$dir/tests/generator/lib.php";
if (!include_once($lib)) {
throw new coding_exception("Plugin $component does not support data generator, missing tests/generator/lib");
}
$classname = $type.'_'.$plugin.'_generator';
$this->generators[$type.'_'.$plugin] = new $classname($this);
if (!class_exists($classname)) {
throw new coding_exception("Component {$component} does not support " .
"data generators yet. Class {$classname} not found.");
}

return $this->generators[$type.'_'.$plugin];
$this->generators[$component] = new $classname($this);
return $this->generators[$component];
}

/**
Expand Down Expand Up @@ -635,6 +646,26 @@ public function create_scale($record=null, array $options=null) {
return $DB->get_record('scale', array('id'=>$id), '*', MUST_EXIST);
}

/**
* Helper method which combines $defaults with the values specified in $record.
* If $record is an object, it is converted to an array.
* Then, for each key that is in $defaults, but not in $record, the value
* from $defaults is copied.
* @param array $defaults the default value for each field with
* @param array|stdClass $record
* @return array updated $record.
*/
public function combine_defaults_and_record(array $defaults, $record) {
$record = (array) $record;

foreach ($defaults as $key => $defaults) {
if (!array_key_exists($key, $record)) {
$record[$key] = $defaults;
}
}
return $record;
}

/**
* Simplified enrolment of user to course using default options.
*
Expand Down
1 change: 1 addition & 0 deletions lib/testing/generator/lib.php
Expand Up @@ -26,6 +26,7 @@
// NOTE: MOODLE_INTERNAL is not verified here because we load this before setup.php!

require_once(__DIR__.'/data_generator.php');
require_once(__DIR__.'/component_generator_base.php');
require_once(__DIR__.'/module_generator.php');
require_once(__DIR__.'/block_generator.php');

15 changes: 1 addition & 14 deletions lib/testing/generator/module_generator.php
Expand Up @@ -34,26 +34,13 @@
* @copyright 2012 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class testing_module_generator {

/**
* @var testing_data_generator
*/
protected $datagenerator;
abstract class testing_module_generator extends component_generator_base {

/**
* @var number of created instances
*/
protected $instancecount = 0;

/**
* Dumb constructor to throw the deprecated notification
* @param testing_data_generator $datagenerator
*/
public function __construct(testing_data_generator $datagenerator) {
$this->datagenerator = $datagenerator;
}

/**
* To be called from data reset code only,
* do not use in tests.
Expand Down
18 changes: 18 additions & 0 deletions lib/testing/tests/generator_test.php
Expand Up @@ -35,6 +35,24 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_test_generator_testcase extends advanced_testcase {
public function test_get_plugin_generator_good_case() {
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
$this->assertInstanceOf('core_question_generator', $generator);
}

public function test_get_plugin_generator_sloppy_name() {
$generator = $this->getDataGenerator()->get_plugin_generator('quiz');
$this->assertDebuggingCalled('Please specify the component you want a generator for as ' .
'mod_quiz, not quiz.', DEBUG_DEVELOPER);
$this->assertInstanceOf('mod_quiz_generator', $generator);
}

public function test_get_plugin_generator_no_component_dir() {
$this->setExpectedException('coding_exception', 'Component core_completion does not support ' .
'generators yet. Missing tests/generator/lib.php.');
$generator = $this->getDataGenerator()->get_plugin_generator('core_completion');
}

public function test_create() {
global $DB;

Expand Down
62 changes: 62 additions & 0 deletions question/tests/generator/lib.php
@@ -0,0 +1,62 @@
<?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/>.

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

/**
* Quiz module test data generator class
*
* @package moodlecore
* @subpackage question
* @copyright 2013 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_question_generator extends component_generator_base {

/**
* @var number of created instances
*/
protected $categorycount = 0;

public function reset() {
$this->categorycount = 0;
}

/**
* Create a new question category.
* @param array|stdClass $record
* @return stdClass question_categories record.
*/
public function create_question_category($record = null) {
global $DB;

$this->categorycount++;

$defaults = array(
'name' => 'Test question category ' . $this->categorycount,
'contextid' => context_system::instance()->id,
'info' => '',
'infoformat' => FORMAT_HTML,
'stamp' => '',
'parent' => 0,
'sortorder' => 999,
);

$record = $this->datagenerator->combine_defaults_and_record($defaults, $record);
$record['id'] = $DB->insert_record('question_categories', $record);
return (object) $record;
}
}
52 changes: 52 additions & 0 deletions question/tests/generator_test.php
@@ -0,0 +1,52 @@
<?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/>.

/**
* Data generators tests
*
* @package moodlecore
* @subpackage questionengine
* @copyright 2013 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

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


/**
* Test data generator
*
* @copyright 2013 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class core_question_generator_testcase extends advanced_testcase {
public function test_create() {
global $DB;

$this->resetAfterTest();
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');

$count = $DB->count_records('question_categories');

$cat = $generator->create_question_category();
$this->assertEquals($count + 1, $DB->count_records('question_categories'));

$cat = $generator->create_question_category(array(
'name' => 'My category', 'sortorder' => 1));
$this->assertSame('My category', $cat->name);
$this->assertSame(1, $cat->sortorder);
}
}

0 comments on commit ba203de

Please sign in to comment.