mirror of
https://github.com/moodle/moodle.git
synced 2025-08-05 00:46:50 +02:00
Merge branch 'MDL-69232-master' of git://github.com/andrewnicols/moodle
This commit is contained in:
commit
0ad85f4148
1 changed files with 157 additions and 88 deletions
|
@ -68,6 +68,9 @@ class behat_hooks extends behat_base {
|
|||
*/
|
||||
protected static $initprocessesfinished = false;
|
||||
|
||||
/** @var bool Whether the first javascript scenario has been seen yet */
|
||||
protected static $firstjavascriptscenarioseen = false;
|
||||
|
||||
/**
|
||||
* @var bool Scenario running
|
||||
*/
|
||||
|
@ -109,40 +112,23 @@ class behat_hooks extends behat_base {
|
|||
*/
|
||||
protected static $scenariotags;
|
||||
|
||||
/**
|
||||
* Hook to capture BeforeSuite event so as to give access to moodle codebase.
|
||||
* This will try and catch any exception and exists if anything fails.
|
||||
*
|
||||
* @param BeforeSuiteScope $scope scope passed by event fired before suite.
|
||||
* @BeforeSuite
|
||||
*/
|
||||
public static function before_suite_hook(BeforeSuiteScope $scope) {
|
||||
// If behat has been initialised then no need to do this again.
|
||||
if (self::$initprocessesfinished) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
self::before_suite($scope);
|
||||
} catch (behat_stop_exception $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives access to moodle codebase, ensures all is ready and sets up the test lock.
|
||||
*
|
||||
* Includes config.php to use moodle codebase with $CFG->behat_*
|
||||
* instead of $CFG->prefix and $CFG->dataroot, called once per suite.
|
||||
* Includes config.php to use moodle codebase with $CFG->behat_* instead of $CFG->prefix and $CFG->dataroot, called
|
||||
* once per suite.
|
||||
*
|
||||
* @BeforeSuite
|
||||
* @param BeforeSuiteScope $scope scope passed by event fired before suite.
|
||||
* @static
|
||||
* @throws behat_stop_exception
|
||||
*/
|
||||
public static function before_suite(BeforeSuiteScope $scope) {
|
||||
public static function before_suite_hook(BeforeSuiteScope $scope) {
|
||||
global $CFG;
|
||||
|
||||
// If behat has been initialised then no need to do this again.
|
||||
if (!self::is_first_scenario()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Defined only when the behat CLI command is running, the moodle init setup process will
|
||||
// read this value and switch to $CFG->behat_dataroot and $CFG->behat_prefix instead of
|
||||
// the normal site.
|
||||
|
@ -170,8 +156,7 @@ class behat_hooks extends behat_base {
|
|||
// before each scenario (accidental user deletes) in the BeforeScenario hook.
|
||||
|
||||
if (!behat_util::is_test_mode_enabled()) {
|
||||
throw new behat_stop_exception('Behat only can run if test mode is enabled. More info in ' .
|
||||
behat_command::DOCS_URL);
|
||||
self::log_and_stop('Behat only can run if test mode is enabled. More info in ' . behat_command::DOCS_URL);
|
||||
}
|
||||
|
||||
// Reset all data, before checking for check_server_status.
|
||||
|
@ -179,20 +164,28 @@ class behat_hooks extends behat_base {
|
|||
behat_util::clean_tables_updated_by_scenario_list();
|
||||
behat_util::reset_all_data();
|
||||
|
||||
// Check if server is running and using same version for cli and apache.
|
||||
// Check if the web server is running and using same version for cli and apache.
|
||||
behat_util::check_server_status();
|
||||
|
||||
// Prevents using outdated data, upgrade script would start and tests would fail.
|
||||
if (!behat_util::is_test_data_updated()) {
|
||||
$commandpath = 'php admin/tool/behat/cli/init.php';
|
||||
throw new behat_stop_exception("Your behat test site is outdated, please run\n\n " .
|
||||
$commandpath . "\n\nfrom your moodle dirroot to drop and install the behat test site again.");
|
||||
$message = <<<EOF
|
||||
Your behat test site is outdated, please run the following command from your Moodle dirroot to drop, and reinstall the Behat test site.
|
||||
|
||||
{$comandpath}
|
||||
|
||||
EOF;
|
||||
self::log_and_stop($message);
|
||||
}
|
||||
|
||||
// Avoid parallel tests execution, it continues when the previous lock is released.
|
||||
test_lock::acquire('behat');
|
||||
|
||||
if (!empty($CFG->behat_faildump_path) && !is_writable($CFG->behat_faildump_path)) {
|
||||
throw new behat_stop_exception('You set $CFG->behat_faildump_path to a non-writable directory');
|
||||
self::log_and_stop(
|
||||
"The \$CFG->behat_faildump_path value is set to a non-writable directory ({$CFG->behat_faildump_path})."
|
||||
);
|
||||
}
|
||||
|
||||
// Handle interrupts on PHP7.
|
||||
|
@ -204,6 +197,25 @@ class behat_hooks extends behat_base {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run final tests before running the suite.
|
||||
*
|
||||
* @BeforeSuite
|
||||
* @param BeforeSuiteScope $scope scope passed by event fired before suite.
|
||||
*/
|
||||
public static function before_suite_final_checks(BeforeSuiteScope $scope) {
|
||||
$happy = defined('BEHAT_TEST');
|
||||
$happy = $happy && defined('BEHAT_SITE_RUNNING');
|
||||
$happy = $happy && php_sapi_name() == 'cli';
|
||||
$happy = $happy && behat_util::is_test_mode_enabled();
|
||||
$happy = $happy && behat_util::is_test_site();
|
||||
|
||||
if (!$happy) {
|
||||
error_log('Behat only can modify the test database and the test dataroot!');
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives access to moodle codebase, to keep track of feature start time.
|
||||
*
|
||||
|
@ -260,56 +272,108 @@ class behat_hooks extends behat_base {
|
|||
}
|
||||
|
||||
/**
|
||||
* Hook to capture before scenario event to get scope.
|
||||
*
|
||||
* @param BeforeScenarioScope $scope scope passed by event fired before scenario.
|
||||
* @BeforeScenario
|
||||
* Helper function to restart the Mink session.
|
||||
*/
|
||||
public function before_scenario_hook(BeforeScenarioScope $scope) {
|
||||
try {
|
||||
$this->before_scenario($scope);
|
||||
} catch (behat_stop_exception $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
exit(1);
|
||||
protected function restart_session(): void {
|
||||
$session = $this->getSession();
|
||||
if ($session->isStarted()) {
|
||||
$session->restart();
|
||||
} else {
|
||||
$session->start();
|
||||
}
|
||||
if ($this->running_javascript() && $this->getSession()->getDriver()->getWebDriverSessionId() === 'session') {
|
||||
throw new DriverException('Unable to create a valid session');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart the session before each non-javascript scenario.
|
||||
*
|
||||
* @BeforeScenario @~javascript
|
||||
* @param BeforeScenarioScope $scope scope passed by event fired before scenario.
|
||||
*/
|
||||
public function before_goutte_scenarios(BeforeScenarioScope $scope) {
|
||||
if ($this->running_javascript()) {
|
||||
// A bug in the BeforeScenario filtering prevents the @~javascript filter on this hook from working
|
||||
// properly.
|
||||
// See https://github.com/Behat/Behat/issues/1235 for further information.
|
||||
return;
|
||||
}
|
||||
|
||||
$this->restart_session();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the session before the first javascript scenario.
|
||||
*
|
||||
* This is treated slightly differently to try to capture when Selenium is not running at all.
|
||||
*
|
||||
* @BeforeScenario @javascript
|
||||
* @param BeforeScenarioScope $scope scope passed by event fired before scenario.
|
||||
*/
|
||||
public function before_first_scenario_start_session(BeforeScenarioScope $scope) {
|
||||
if (!self::is_first_javascript_scenario()) {
|
||||
// The first Scenario has started.
|
||||
// The `before_subsequent_scenario_start_session` function will restart the session instead.
|
||||
return;
|
||||
}
|
||||
self::$firstjavascriptscenarioseen = true;
|
||||
|
||||
$docsurl = behat_command::DOCS_URL;
|
||||
$driverexceptionmsg = <<<EOF
|
||||
|
||||
The Selenium or WebDriver server is not running. You must start it to run tests that involve Javascript.
|
||||
See {$docsurl} for more information.
|
||||
|
||||
The following debugging information is available:
|
||||
|
||||
EOF;
|
||||
|
||||
|
||||
try {
|
||||
$this->restart_session();
|
||||
} catch (CurlExec | DriverException $e) {
|
||||
// The CurlExec Exception is thrown by WebDriver.
|
||||
self::log_and_stop(
|
||||
$driverexceptionmsg . '. ' .
|
||||
$e->getMessage() . "\n\n" .
|
||||
format_backtrace($e->getTrace(), true)
|
||||
);
|
||||
} catch (UnknownError $e) {
|
||||
// Generic 'I have no idea' Selenium error. Custom exception to provide more feedback about possible solutions.
|
||||
self::log_and_stop(
|
||||
$e->getMessage() . "\n\n" .
|
||||
format_backtrace($e->getTrace(), true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the session before each javascript scenario.
|
||||
*
|
||||
* Note: Before the first scenario the @see before_first_scenario_start_session() function is used instead.
|
||||
*
|
||||
* @BeforeScenario @javascript
|
||||
* @param BeforeScenarioScope $scope scope passed by event fired before scenario.
|
||||
*/
|
||||
public function before_subsequent_scenario_start_session(BeforeScenarioScope $scope) {
|
||||
if (self::is_first_javascript_scenario()) {
|
||||
// The initial init has not yet finished.
|
||||
// The `before_first_scenario_start_session` function will have started the session instead.
|
||||
return;
|
||||
}
|
||||
|
||||
$this->restart_session();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the test environment.
|
||||
*
|
||||
* @BeforeScenario
|
||||
* @param BeforeScenarioScope $scope scope passed by event fired before scenario.
|
||||
* @throws behat_stop_exception If here we are not using the test database it should be because of a coding error
|
||||
*/
|
||||
public function before_scenario(BeforeScenarioScope $scope) {
|
||||
global $DB, $CFG;
|
||||
|
||||
// As many checks as we can.
|
||||
if (!defined('BEHAT_TEST') ||
|
||||
!defined('BEHAT_SITE_RUNNING') ||
|
||||
php_sapi_name() != 'cli' ||
|
||||
!behat_util::is_test_mode_enabled() ||
|
||||
!behat_util::is_test_site()) {
|
||||
throw new behat_stop_exception('Behat only can modify the test database and the test dataroot!');
|
||||
}
|
||||
|
||||
$moreinfo = 'More info in ' . behat_command::DOCS_URL;
|
||||
$driverexceptionmsg = 'Selenium server is not running, you need to start it to run tests that involve Javascript. ' . $moreinfo;
|
||||
try {
|
||||
$session = $this->getSession();
|
||||
if (!$session->isStarted()) {
|
||||
$session->start();
|
||||
}
|
||||
} catch (CurlExec $e) {
|
||||
// Exception thrown by WebDriver, so only @javascript tests will be caugth; in
|
||||
// behat_util::check_server_status() we already checked that the server is running.
|
||||
throw new behat_stop_exception($driverexceptionmsg);
|
||||
} catch (DriverException $e) {
|
||||
throw new behat_stop_exception($driverexceptionmsg);
|
||||
} catch (UnknownError $e) {
|
||||
// Generic 'I have no idea' Selenium error. Custom exception to provide more feedback about possible solutions.
|
||||
throw new behat_stop_exception($e->getMessage());
|
||||
}
|
||||
|
||||
public function before_scenario_hook(BeforeScenarioScope $scope) {
|
||||
global $DB;
|
||||
$suitename = $scope->getSuite()->getName();
|
||||
|
||||
// Register behat selectors for theme, if suite is changed. We do it for every suite change.
|
||||
|
@ -343,9 +407,6 @@ class behat_hooks extends behat_base {
|
|||
|
||||
}
|
||||
|
||||
// Reset mink session between the scenarios.
|
||||
$session->reset();
|
||||
|
||||
// Reset $SESSION.
|
||||
\core\session\manager::init_empty_session();
|
||||
|
||||
|
@ -698,6 +759,15 @@ class behat_hooks extends behat_base {
|
|||
return !(self::$initprocessesfinished);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the first scenario of the suite is running
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function is_first_javascript_scenario(): bool {
|
||||
return !self::$firstjavascriptscenarioseen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a set of component selectors.
|
||||
*
|
||||
|
@ -737,20 +807,19 @@ class behat_hooks extends behat_base {
|
|||
* @param BeforeStepScope $scope
|
||||
* @BeforeStep
|
||||
*/
|
||||
public function first_step_setup_complete(BeforeStepScope $scope) {
|
||||
public function first_step_setup_complete(BeforeStepScope $scope): void {
|
||||
self::$initprocessesfinished = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a notification, and then exit.
|
||||
*
|
||||
* @param string $message The content to dispaly
|
||||
*/
|
||||
protected static function log_and_stop(string $message): void {
|
||||
error_log($message);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Behat stop exception
|
||||
*
|
||||
* This exception is thrown from before suite or scenario if any setup problem found.
|
||||
*
|
||||
* @package core_test
|
||||
* @copyright 2016 Rajesh Taneja <rajesh@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class behat_stop_exception extends \Exception {
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue