diff --git a/blocks/online_users/tests/generator/lib.php b/blocks/online_users/tests/generator/lib.php new file mode 100644 index 00000000000..d762f42a191 --- /dev/null +++ b/blocks/online_users/tests/generator/lib.php @@ -0,0 +1,63 @@ +. + +/** + * block_online_users data generator + * + * @package block_online_users + * @category phpunit + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + + +/** + * Page module PHPUnit data generator class + * + * @package mod_page + * @category phpunit + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class block_online_users_generator extends phpunit_block_generator { + + /** + * Create new block instance + * @param array|stdClass $record + * @param array $options + * @return stdClass activity record with extra cmid field + */ + public function create_instance($record = null, array $options = null) { + global $DB, $CFG; + require_once("$CFG->dirroot/mod/page/locallib.php"); + + $this->instancecount++; + + $record = (object)(array)$record; + $options = (array)$options; + + $record = $this->prepare_record($record); + + $id = $DB->insert_record('block_instances', $record); + context_block::instance($id); + + $instance = $DB->get_record('block_instances', array('id'=>$id), '*', MUST_EXIST); + + return $instance; + } +} diff --git a/blocks/online_users/tests/generator_test.php b/blocks/online_users/tests/generator_test.php new file mode 100644 index 00000000000..726e778765d --- /dev/null +++ b/blocks/online_users/tests/generator_test.php @@ -0,0 +1,57 @@ +. + +/** + * PHPUnit data generator tests + * + * @package block_online_users + * @category phpunit + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + + +/** + * PHPUnit data generator testcase + * + * @package block_online_users + * @category phpunit + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class block_online_users_generator_testcase extends advanced_testcase { + public function test_geenrator() { + global $DB; + + $this->resetAfterTest(true); + + $beforeblocks = $DB->count_records('block_instances'); + $beforecontexts = $DB->count_records('context'); + + /** @var block_online_users_generator $generator */ + $generator = $this->getDataGenerator()->get_plugin_generator('block_online_users'); + $this->assertInstanceOf('block_online_users_generator', $generator); + $this->assertEquals('online_users', $generator->get_blockname()); + + $generator->create_instance(); + $generator->create_instance(); + $bi = $generator->create_instance(); + $this->assertEquals($beforeblocks+3, $DB->count_records('block_instances')); + + } +} diff --git a/lib/phpunit/generatorlib.php b/lib/phpunit/generatorlib.php index f01893e6e1e..6247e19c2af 100644 --- a/lib/phpunit/generatorlib.php +++ b/lib/phpunit/generatorlib.php @@ -25,17 +25,24 @@ defined('MOODLE_INTERNAL') || die(); + /** * Data generator for unit tests + * + * @package core + * @category phpunit + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class phpunit_data_generator { protected $usercounter = 0; protected $categorycount = 0; protected $coursecount = 0; - protected $blockcount = 0; - protected $modulecount = 0; protected $scalecount = 0; + /** @var array list of plugin generators */ + protected $generators = array(); + /** * To be called from data reset code only, * do not use in tests. @@ -45,9 +52,32 @@ class phpunit_data_generator { $this->usercounter = 0; $this->categorycount = 0; $this->coursecount = 0; - $this->blockcount = 0; - $this->modulecount = 0; $this->scalecount = 0; + + foreach($this->generators as $generator) { + $generator->reset(); + } + } + + public function get_plugin_generator($component) { + list($type, $plugin) = normalize_component($component); + + if ($type !== 'mod' and $type !== 'block') { + throw new coding_exception("Plugin type $type does not support generators yet"); + } + + $dir = get_plugin_directory($type, $plugin); + + 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); + } + + return $this->generators[$type.'_'.$plugin]; } /** @@ -171,7 +201,7 @@ class phpunit_data_generator { $record['descriptionformat'] = 0; } - if ($record['parent'] == 0) { + if (empty($record['parent'])) { $parent = new stdClass(); $parent->path = ''; $parent->depth = 0; @@ -313,41 +343,8 @@ class phpunit_data_generator { * @return stdClass block instance record */ public function create_block($blockname, $record=null, array $options=null) { - global $DB; - - $this->blockcount++; - $i = $this->blockcount; - - $record = (array)$record; - - $record['blockname'] = $blockname; - - //TODO: use block callbacks - - if (!isset($record['parentcontextid'])) { - $record['parentcontextid'] = context_system::instance()->id; - } - - if (!isset($record['showinsubcontexts'])) { - $record['showinsubcontexts'] = 1; - } - - if (!isset($record['pagetypepattern'])) { - $record['pagetypepattern'] = ''; - } - - if (!isset($record['subpagepattern'])) { - $record['subpagepattern'] = ''; - } - - if (!isset($record['defaultweight'])) { - $record['defaultweight'] = ''; - } - - $biid = $DB->insert_record('block_instances', $record); - context_block::instance($biid); - - return $DB->get_record('block_instances', array('id'=>$biid), '*', MUST_EXIST); + $generator = $this->get_plugin_generator('block_'.$blockname); + return $generator->create_instance($record, $options); } /** @@ -358,63 +355,8 @@ class phpunit_data_generator { * @return stdClass activity record */ public function create_module($modulename, $record=null, array $options=null) { - global $DB, $CFG; - require_once("$CFG->dirroot/course/lib.php"); - - $this->modulecount++; - $i = $this->modulecount; - - $record = (array)$record; - $options = (array)$options; - - if (!isset($record['name'])) { - $record['name'] = get_string('pluginname', $modulename).' '.$i; - } - - if (!isset($record['intro'])) { - $record['intro'] = 'Test module '.$i; - } - - if (!isset($record['introformat'])) { - $record['introformat'] = FORMAT_MOODLE; - } - - if (!isset($options['section'])) { - $options['section'] = 1; - } - - //TODO: use module callbacks - - if ($modulename === 'page') { - if (!isset($record['content'])) { - $record['content'] = 'Test page content'; - } - if (!isset($record['contentformat'])) { - $record['contentformat'] = FORMAT_MOODLE; - } - - } else { - error('TODO: only mod_page is supported in data generator for now'); - } - - $id = $DB->insert_record($modulename, $record); - - $cm = new stdClass(); - $cm->course = $record['course']; - $cm->module = $DB->get_field('modules', 'id', array('name'=>$modulename)); - $cm->section = $options['section']; - $cm->instance = $id; - $cm->id = $DB->insert_record('course_modules', $cm); - - $cm->coursemodule = $cm->id; - add_mod_to_section($cm); - - context_module::instance($cm->id); - - $instance = $DB->get_record($modulename, array('id'=>$id), '*', MUST_EXIST); - $instance->cmid = $cm->id; - - return $instance; + $generator = $this->get_plugin_generator('mod_'.$modulename); + return $generator->create_instance($record, $options); } /** @@ -468,3 +410,191 @@ class phpunit_data_generator { return $DB->get_record('scale', array('id'=>$id), '*', MUST_EXIST); } } + + +/** + * Module generator base class. + * + * Extend in mod/xxxx/tests/generator/lib.php as class mod_xxxx_generator. + * + * @package core + * @category phpunit + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +abstract class phpunit_module_generator { + /** @var phpunit_data_generator@var */ + protected $datagenerator; + + /** @var number of created instances */ + protected $instancecount = 0; + + public function __construct(phpunit_data_generator $datagenerator) { + $this->datagenerator = $datagenerator; + } + + /** + * To be called from data reset code only, + * do not use in tests. + * @return void + */ + public function reset() { + $this->instancecount = 0; + } + + /** + * Returns module name + * @return string name of module that this class describes + * @throws coding_exception if class invalid + */ + public function get_modulename() { + $matches = null; + if (!preg_match('/^mod_([a-z0-9]+)_generator$/', get_class($this), $matches)) { + throw new coding_exception('Invalid module generator class name: '.get_class($this)); + } + + if (empty($matches[1])) { + throw new coding_exception('Invalid module generator class name: '.get_class($this)); + } + return $matches[1]; + } + + /** + * Create course module and link it to course + * @param stdClass $instance + * @param array $options: section, visible + * @return stdClass $cm instance + */ + protected function create_course_module(stdClass $instance, array $options) { + global $DB, $CFG; + require_once("$CFG->dirroot/course/lib.php"); + + $modulename = $this->get_modulename(); + + $cm = new stdClass(); + $cm->course = $instance->course; + $cm->module = $DB->get_field('modules', 'id', array('name'=>$modulename)); + $cm->instance = $instance->id; + $cm->section = isset($options['section']) ? $options['section'] : 0; + $cm->idnumber = isset($options['idnumber']) ? $options['idnumber'] : 0; + $cm->added = time(); + + $columns = $DB->get_columns('course_modules'); + foreach ($options as $key=>$value) { + if ($key === 'id' or !isset($columns[$key])) { + continue; + } + if (property_exists($cm, $key)) { + continue; + } + $cm->$key = $value; + } + + $cm->id = $DB->insert_record('course_modules', $cm); + $cm->coursemodule = $cm->id; + + add_mod_to_section($cm); + + $cm = get_coursemodule_from_id($modulename, $cm->id, $cm->course, true, MUST_EXIST); + + context_module::instance($cm->id); + + return $cm; + } + + /** + * Create a test module + * @param array|stdClass $record + * @param array $options + * @return stdClass activity record + */ + abstract public function create_instance($record = null, array $options = null); +} + + +/** + * Block generator base class. + * + * Extend in blocks/xxxx/tests/generator/lib.php as class block_xxxx_generator. + * + * @package core + * @category phpunit + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +abstract class phpunit_block_generator { + /** @var phpunit_data_generator@var */ + protected $datagenerator; + + /** @var number of created instances */ + protected $instancecount = 0; + + public function __construct(phpunit_data_generator $datagenerator) { + $this->datagenerator = $datagenerator; + } + + /** + * To be called from data reset code only, + * do not use in tests. + * @return void + */ + public function reset() { + $this->instancecount = 0; + } + + /** + * Returns block name + * @return string name of block that this class describes + * @throws coding_exception if class invalid + */ + public function get_blockname() { + $matches = null; + if (!preg_match('/^block_([a-z0-9_]+)_generator$/', get_class($this), $matches)) { + throw new coding_exception('Invalid block generator class name: '.get_class($this)); + } + + if (empty($matches[1])) { + throw new coding_exception('Invalid block generator class name: '.get_class($this)); + } + return $matches[1]; + } + + /** + * Fill in record defaults + * @param stdClass $record + * @return stdClass + */ + protected function prepare_record(stdClass $record) { + $record->blockname = $this->get_blockname(); + if (!isset($record->parentcontextid)) { + $record->parentcontextid = context_system::instance()->id; + } + if (!isset($record->showinsubcontexts)) { + $record->showinsubcontexts = 1; + } + if (!isset($record->pagetypepattern)) { + $record->pagetypepattern = ''; + } + if (!isset($record->subpagepattern)) { + $record->subpagepattern = null; + } + if (!isset($record->defaultregion)) { + $record->defaultregion = ''; + } + if (!isset($record->defaultweight)) { + $record->defaultweight = ''; + } + if (!isset($record->configdata)) { + $record->configdata = null; + } + return $record; + } + + /** + * Create a test block + * @param array|stdClass $record + * @param array $options + * @return stdClass activity record + */ + abstract public function create_instance($record = null, array $options = null); +} \ No newline at end of file diff --git a/lib/tests/phpunit_test.php b/lib/tests/phpunit_test.php index 944fdfefdb2..95e8393a16b 100644 --- a/lib/tests/phpunit_test.php +++ b/lib/tests/phpunit_test.php @@ -191,4 +191,71 @@ class core_phpunit_advanced_testcase extends advanced_testcase { $this->assertEquals(0, $USER->id); $this->assertSame($_SESSION['USER'], $USER); } + + public function test_getDataGenerator() { + $generator = $this->getDataGenerator(); + $this->assertInstanceOf('phpunit_data_generator', $generator); + } +} + + +/** + * Test data generator + * + * @package core + * @category phpunit + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class core_phpunit_generator_testcase extends advanced_testcase { + public function test_create() { + global $DB; + + $this->resetAfterTest(true); + $generator = $this->getDataGenerator(); + + $count = $DB->count_records('user'); + $user = $generator->create_user(); + $this->assertEquals($count+1, $DB->count_records('user')); + + $count = $DB->count_records('course_categories'); + $category = $generator->create_category(); + $this->assertEquals($count+1, $DB->count_records('course_categories')); + + $count = $DB->count_records('course'); + $course = $generator->create_course(); + $this->assertEquals($count+1, $DB->count_records('course')); + + $section = $generator->create_course_section(array('course'=>$course->id, 'section'=>3)); + $this->assertEquals($course->id, $section->course); + + $scale = $generator->create_scale(); + $this->assertNotEmpty($scale); + } + + public function test_create_module() { + global $CFG, $SITE; + if (!file_exists("$CFG->dirroot/mod/page/")) { + $this->markTestSkipped('Can not find standard Page module'); + } + + $this->resetAfterTest(true); + $generator = $this->getDataGenerator(); + + $page = $generator->create_module('page', array('course'=>$SITE->id)); + $this->assertNotEmpty($page); + } + + public function test_create_block() { + global $CFG; + if (!file_exists("$CFG->dirroot/blocks/online_users/")) { + $this->markTestSkipped('Can not find standard Online users block'); + } + + $this->resetAfterTest(true); + $generator = $this->getDataGenerator(); + + $page = $generator->create_block('online_users'); + $this->assertNotEmpty($page); + } } diff --git a/mod/page/tests/generator/lib.php b/mod/page/tests/generator/lib.php new file mode 100644 index 00000000000..f0a2fe77d5d --- /dev/null +++ b/mod/page/tests/generator/lib.php @@ -0,0 +1,84 @@ +. + +/** + * mod_page data generator + * + * @package mod_page + * @category phpunit + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + + +/** + * Page module PHPUnit data generator class + * + * @package mod_page + * @category phpunit + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class mod_page_generator extends phpunit_module_generator { + + /** + * Create new page module instance + * @param array|stdClass $record + * @param array $options + * @return stdClass activity record with extra cmid field + */ + public function create_instance($record = null, array $options = null) { + global $DB, $CFG; + require_once("$CFG->dirroot/mod/page/locallib.php"); + + $this->instancecount++; + $i = $this->instancecount; + + $record = (object)(array)$record; + $options = (array)$options; + + if (!isset($record->name)) { + $record->name = get_string('pluginname', 'page').' '.$i; + } + if (!isset($record->intro)) { + $record->intro = 'Test page '.$i; + } + if (!isset($record->introformat)) { + $record->introformat = FORMAT_MOODLE; + } + if (!isset($record->content)) { + $record->content = 'Test page content'; + } + if (!isset($record->contentformat)) { + $record->contentformat = FORMAT_MOODLE; + } + if (!isset($record->display)) { + $record->display = RESOURCELIB_DISPLAY_AUTO; + } + $record->timemodified = time(); + + $id = $DB->insert_record('page', $record); + $instance = $DB->get_record('page', array('id'=>$id), '*', MUST_EXIST); + + $cm = $this->create_course_module($instance, $options); + + $instance->cmid = $cm->id; + + return $instance; + } +} diff --git a/mod/page/tests/generator_test.php b/mod/page/tests/generator_test.php new file mode 100644 index 00000000000..79dffbb06d9 --- /dev/null +++ b/mod/page/tests/generator_test.php @@ -0,0 +1,63 @@ +. + +/** + * PHPUnit data generator tests + * + * @package mod_page + * @category phpunit + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + + +/** + * PHPUnit data generator testcase + * + * @package mod_page + * @category phpunit + * @copyright 2012 Petr Skoda {@link http://skodak.org} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class mod_page_generator_testcase extends advanced_testcase { + public function test_geenrator() { + global $DB, $SITE; + + $this->resetAfterTest(true); + + $this->assertEquals(0, $DB->count_records('page')); + + /** @var mod_page_generator $generator */ + $generator = $this->getDataGenerator()->get_plugin_generator('mod_page'); + $this->assertInstanceOf('mod_page_generator', $generator); + $this->assertEquals('page', $generator->get_modulename()); + + $generator->create_instance(array('course'=>$SITE->id)); + $generator->create_instance(array('course'=>$SITE->id)); + $page = $generator->create_instance(array('course'=>$SITE->id)); + $this->assertEquals(3, $DB->count_records('page')); + + $cm = get_coursemodule_from_instance('page', $page->id); + $this->assertEquals($page->id, $cm->instance); + $this->assertEquals('page', $cm->modname); + $this->assertEquals($SITE->id, $cm->course); + + $context = context_module::instance($cm->id); + $this->assertEquals($page->cmid, $context->instanceid); + } +}