From 7f541ea3eda914f0cd47ce66baa6c43e9c09c061 Mon Sep 17 00:00:00 2001 From: David Monllao Date: Wed, 10 Oct 2012 10:50:44 +0800 Subject: [PATCH] MDL-37046 behat: Adding web-based tests runner Uses phpunit test environment to execute the functional testing, adding steps definitions list and tests runner actions --- admin/tool/behat/locallib.php | 333 ++++++++++++++++++++++++++++++++++ admin/tool/behat/styles.css | 3 + lib/setup.php | 6 + 3 files changed, 342 insertions(+) create mode 100644 admin/tool/behat/locallib.php create mode 100644 admin/tool/behat/styles.css diff --git a/admin/tool/behat/locallib.php b/admin/tool/behat/locallib.php new file mode 100644 index 00000000000..0203634beac --- /dev/null +++ b/admin/tool/behat/locallib.php @@ -0,0 +1,333 @@ +. + +/** + * Behat commands + * + * @package tool_behat + * @copyright 2012 David Monllaó + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once($CFG->libdir . '/filestorage/file_exceptions.php'); +require_once($CFG->libdir . '/phpunit/bootstraplib.php'); +require_once($CFG->libdir . '/phpunit/classes/util.php'); + +class tool_behat { + + /** + * Displays basic info about acceptance tests + */ + public static function info() { + + $html = tool_behat::get_info(); + $html .= tool_behat::get_steps_definitions_form(); + $html .= tool_behat::get_run_tests_form(); + + echo $html; + } + + + /** + * Lists the available steps definitions + */ + public static function stepsdefinitions() { + global $CFG; + + confirm_sesskey(); + tool_behat::check_behat_setup(); + + if ($filter = optional_param('filter', false, PARAM_ALPHANUMEXT)) { + $filteroption = ' -d ' . $filter; + } else { + $filteroption = ' -di'; + } + + $currentcwd = getcwd(); + chdir($CFG->behatpath); + exec('bin/behat' . $filteroption, $steps, $code); + chdir($currentcwd); + + // Outputing steps. + $html = tool_behat::get_steps_definitions_form($filter); + + $content = ''; + if ($steps) { + foreach ($steps as $line) { + + // Skipping the step definition context. + if (strpos($line, '#') == 0) { + $content .= htmlentities($line) . '
'; + } + } + } + + if ($content === '') { + $content = get_string('nostepsdefinitions', 'tool_behat'); + } + + $html .= html_writer::tag('div', $content, array('id' => 'steps-definitions')); + echo $html; + } + + + /** + * Creates a file listing all the moodle with features and steps definitions + */ + public static function buildconfigfile() { + // TODO + } + + /** + * Runs the acceptance tests + */ + public static function runtests() { + global $CFG; + + confirm_sesskey(); + tool_behat::check_behat_setup(); + + @set_time_limit(0); + + $tagsoption = ''; + if ($tags = optional_param('tags', false, PARAM_ALPHANUMEXT)) { + $tagsoption = ' --tags ' . $tags; + } + + // Switching database and dataroot to test environment. + tool_behat::enable_test_environment(); + $currentcwd = getcwd(); + + // Outputting runner form and tests results. + echo tool_behat::get_run_tests_form($tags); + + chdir($CFG->behatpath); + passthru('bin/behat --format html' . $tagsoption, $code); + + // Switching back to regular environment + tool_behat::disable_test_environment(); + chdir($currentcwd); + } + + + /** + * Checks whether the test database and dataroot is ready + * Stops execution if something went wrong + */ + private static function test_environment_problem() { + global $CFG; + + // phpunit --diag returns nothing if the test environment is set up correctly. + $currentcwd = getcwd(); + chdir($CFG->dirroot . '/' . $CFG->admin . '/tool/phpunit/cli'); + exec("php util.php --diag", $output, $code); + chdir($currentcwd); + + // If something is not ready stop execution and display the CLI command output. + if ($code != 0) { + notice(implode(' ', $output)); + } + } + + /** + * Checks the behat setup + */ + private static function check_behat_setup() { + global $CFG; + + // Moodle setting. + if (empty($CFG->behatpath)) { + $msg = get_string('nobehatpath', 'tool_behat'); + $url = $CFG->wwwroot . '/' . $CFG->admin . '/settings.php?section=systempaths'; + + if (!CLI_SCRIPT) { + $msg .= ' ' . html_writer::tag('a', get_string('systempaths', 'admin'), array('href' => $url)); + } + notice($msg); + } + + // Behat test command. + $currentcwd = getcwd(); + chdir($CFG->behatpath); + exec('bin/behat --help', $output, $code); + chdir($currentcwd); + + if ($code != 0) { + notice(get_string('wrongbehatsetup', 'tool_behat')); + } + } + + /** + * Enables test mode checking the test environment setup + * + * Stores a file in dataroot/behat to allow Moodle swap to + * test database and dataroot before the initial set up + * + * @throws file_exception + */ + public static function enable_test_environment() { + global $CFG; + + confirm_sesskey(); + + if (tool_behat::is_test_environment_enabled()) { + debugging('Test environment was already enabled'); + return; + } + + // Check that PHPUnit test environment is correctly set up. + tool_behat::test_environment_problem(); + + $behatdir = $CFG->dataroot . '/behat'; + + if (!is_dir($behatdir)) { + if (!mkdir($behatdir, $CFG->directorypermissions, true)) { + throw new file_exception('storedfilecannotcreatefiledirs'); + } + } + + if (!is_writable($behatdir)) { + throw new file_exception('storedfilecannotcreatefiledirs'); + } + + $content = '$CFG->phpunit_prefix and $CFG->phpunit_dataroot are currently used as $CFG->prefix and $CFG->dataroot'; + $filepath = $behatdir . '/test_environment_enabled.txt'; + if (!file_put_contents($filepath, $content)) { + throw new file_exception('cannotcreatefile', $filepath); + } + + } + + /** + * Disables test mode + */ + public static function disable_test_environment() { + global $CFG; + + confirm_sesskey(); + + $testenvfile = $CFG->dataroot . '/behat/test_environment_enabled.txt'; + + if (!tool_behat::is_test_environment_enabled()) { + debugging('Test environment was already disabled'); + } else { + unlink($testenvfile); + } + } + + /** + * Checks whether test environment is enabled or disabled + */ + public static function is_test_environment_enabled() { + global $CFG; + + $testenvfile = $CFG->dataroot . '/behat/test_environment_enabled.txt'; + if (file_exists($testenvfile)) { + return true; + } + + return false; + } + + /** + * Returns the installation instructions + * + * (hardcoded in English) + * + * @return string + */ + private static function get_info() { + global $OUTPUT; + + $html = $OUTPUT->box_start(); + $html .= html_writer::tag('h1', 'Info'); + $info = 'This tool makes use of the phpunit test environment, during the automatic acceptance tests execution the site uses the test database and dataroot directories so this tool IS NOT intended to be used in production sites.'; + $html .= html_writer::tag('div', $info); + + $html .= html_writer::tag('h1', 'Installation'); + $installinstructions = '1.- Follow the PHPUnit installation instructions to set up the testing environment $CFG->wwwroot/admin/tool/phpunit/index.php
'; + $installinstructions .= '2.- Follow the moodle-acceptance-test installation instructions https://github.com/dmonllao/behat-moodle
'; + $installinstructions .= '3.- Set up the \'config_file_path\' param in /MOODLE-ACCEPTANCE-TEST/ROOT/PATH/behat.yml pointing to $CFG->dataroot/behat/config.yml (for example /YOUR/MOODLEDATA/PATH/behat/config.yml)
'; + $installinstructions .= '4.- Set up $CFG->behatpath in your config.php with the path of your moodle-acceptance-test installation (for example /MOODLE-ACCEPTANCE-TEST/ROOT/PATH)
'; + $html .= html_writer::tag('div', $installinstructions); + $html .= $OUTPUT->box_end(); + + return $html; + } + + /** + * Returns the steps definitions form + * @param string $filter To filter the steps definitions list by keyword + * @return string + */ + private static function get_steps_definitions_form($filter = false) { + global $OUTPUT; + + if ($filter === false) { + $filter = ''; + } else { + $filter = s($filter); + } + + $html = $OUTPUT->box_start(); + $html .= '
'; + $html .= '

'; + $html .= '

'; + $html .= ' '; + $html .= ' (all steps definitions if empty)'; + $html .= '

'; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= '
'; + $html .= '
'; + $html .= $OUTPUT->box_end(); + + return $html; + } + + /** + * Returns the run tests form + * @param string $tags To execute only the tests that matches the specified tag + * @return string + */ + private static function get_run_tests_form($tags = false) { + global $OUTPUT; + + if ($tags === false) { + $tags = ''; + } else { + $tags = s($tags); + } + + $html = $OUTPUT->box_start(); + $html .= '
'; + $html .= '

'; + $html .= '

'; + $html .= ' '; + $html .= ' (all available tests if empty)'; + $html .= '

'; + $html .= ''; + $html .= ''; + $html .= ''; + $html .= '
'; + $html .= '
'; + $html .= $OUTPUT->box_end(); + + return $html; + } + +} diff --git a/admin/tool/behat/styles.css b/admin/tool/behat/styles.css new file mode 100644 index 00000000000..e0581b72548 --- /dev/null +++ b/admin/tool/behat/styles.css @@ -0,0 +1,3 @@ +#region-main-box #behat .summary { position: relative;} +div#steps-definitions{border-style:solid;border-width:1px;border-color:#BBB;padding:5px;margin:auto;width:50%;} +#page-admin-tool-behat-index{padding-top: 0px;} \ No newline at end of file diff --git a/lib/setup.php b/lib/setup.php index f25301f14ae..2f52dc909dd 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -90,6 +90,12 @@ if (!isset($CFG->wwwroot) or $CFG->wwwroot === 'http://example.com/moodle') { exit(1); } +// If acceptance testing mode is enabled use test database and dataroot +if (file_exists($CFG->dataroot . '/behat/test_environment_enabled.txt')) { + $CFG->prefix = $CFG->phpunit_prefix; + $CFG->dataroot = $CFG->phpunit_dataroot; +} + // Define admin directory if (!isset($CFG->admin)) { // Just in case it isn't defined in config.php $CFG->admin = 'admin'; // This is relative to the wwwroot and dirroot