Skip to content

Commit

Permalink
MDL-69232 behat: Make selenium start more fault tolerant
Browse files Browse the repository at this point in the history
The session was previously only started once, but has now been moved to
restart between each test. Because of this the `$session->start()` is
now called more frequently which exposes a pre-existing issue whereby
Selenium will periodically fail to start.

When the session was only started at the beginning of the test, and at
occasional other times, it made sense to always stop the test runner
because it signified an issue with obtaining the session at all.

Since the session is restarted more frequently, and now between every
test, it no longer makes sense to do this. The test should only be
_stopped_ if the first attempt to obtain the Session fails. Once a
Session has been retrieved at least once it no longer makes sense to
assume that the failure was a configuration failure, but a connection
failure. Therefore subsequent tests should be attempted.
  • Loading branch information
andrewnicols committed Jul 10, 2020
1 parent 5e99058 commit 5306f2f
Showing 1 changed file with 43 additions and 29 deletions.
72 changes: 43 additions & 29 deletions lib/tests/behat/behat_hooks.php
Expand Up @@ -293,6 +293,21 @@ public function before_scenario_hook(BeforeScenarioScope $scope) {
}
}

/**
* Helper function to restart the Mink session.
*/
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 valid session');
}
}

/**
* Resets the test environment.
*
Expand All @@ -302,33 +317,35 @@ public function before_scenario_hook(BeforeScenarioScope $scope) {
public function before_scenario(BeforeScenarioScope $scope) {
global $DB, $CFG;

$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();
if (self::$initprocessesfinished) {
$this->restart_session();
} else {
$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 {
$this->restart_session();
} 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 . '. ' .
$e->getMessage() . "\n\n" .
format_backtrace($e->getTrace(), true)
);
} catch (DriverException $e) {
throw new behat_stop_exception(
$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.
throw new behat_stop_exception(
$e->getMessage() . "\n\n" .
format_backtrace($e->getTrace(), true)
);
}
} 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 . '. ' .
$e->getMessage() . "\n\n" .
format_backtrace($e->getTrace(), true)
);
} catch (DriverException $e) {
throw new behat_stop_exception(
$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.
throw new behat_stop_exception(
$e->getMessage() . "\n\n" .
format_backtrace($e->getTrace(), true)
);
}

$suitename = $scope->getSuite()->getName();
Expand Down Expand Up @@ -364,9 +381,6 @@ public function before_scenario(BeforeScenarioScope $scope) {

}

// Reset mink session between the scenarios.
$session->reset();

// Reset $SESSION.
\core\session\manager::init_empty_session();

Expand Down

0 comments on commit 5306f2f

Please sign in to comment.