From f49cede7943cabfcbfa0293f71d97b219fdc70b2 Mon Sep 17 00:00:00 2001 From: David Monllao Date: Thu, 19 Dec 2013 15:48:03 +0800 Subject: [PATCH] MDL-43404 behat: Avoid failures at framework level as much as possible - Move them to i_look_for_exceptions() so they will be thrown at a step (scenario) level. - Accept alerts only when they are detected to avoid all the following scenarios to be failing; they would continue executing, but they will all fail if the alert is still there - Add a step to avoid add_scorm.feature to fail - Refine the UnknownError catch --- lib/tests/behat/behat_hooks.php | 62 ++++++++++++++++++++++--- mod/scorm/tests/behat/add_scorm.feature | 1 + 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/lib/tests/behat/behat_hooks.php b/lib/tests/behat/behat_hooks.php index 7f2ac7aa2a4..b521638d20a 100644 --- a/lib/tests/behat/behat_hooks.php +++ b/lib/tests/behat/behat_hooks.php @@ -67,6 +67,16 @@ class behat_hooks extends behat_base { */ protected static $initprocessesfinished = false; + /** + * Some exceptions can only be caught in a before or after step hook, + * they can not be thrown there as they will provoke a framework level + * failure, but we can store them here to fail the step in i_look_for_exceptions() + * which result will be parsed by the framework as the last step result. + * + * @var Null or the exception last step throw in the before or after hook. + */ + protected static $currentstepexception = null; + /** * Gives access to moodle codebase, ensures all is ready and sets up the test lock. * @@ -215,12 +225,22 @@ class behat_hooks extends behat_base { /** * Wait for JS to complete before beginning interacting with the DOM. * - * Executed only when running against a real browser. + * Executed only when running against a real browser. We wrap it + * all in a try & catch to forward the exception to i_look_for_exceptions + * so the exception will be at scenario level, which causes a failure, by + * default would be at framework level, which will stop the execution of + * the run. * * @BeforeStep @javascript */ public function before_step_javascript($event) { - $this->wait_for_pending_js(); + + try { + $this->wait_for_pending_js(); + self::$currentstepexception = null; + } catch (Exception $e) { + self::$currentstepexception = $e; + } } /** @@ -229,12 +249,33 @@ class behat_hooks extends behat_base { * With this we ensure that there are not AJAX calls * still in progress. * - * Executed only when running against a real browser. + * Executed only when running against a real browser. We wrap it + * all in a try & catch to forward the exception to i_look_for_exceptions + * so the exception will be at scenario level, which causes a failure, by + * default would be at framework level, which will stop the execution of + * the run. * * @AfterStep @javascript */ public function after_step_javascript($event) { - $this->wait_for_pending_js(); + + try { + $this->wait_for_pending_js(); + self::$currentstepexception = null; + } catch (UnexpectedAlertOpen $e) { + self::$currentstepexception = $e; + + // Accepting the alert so the framework can continue properly running + // the following scenarios. Some browsers already closes the alert, so + // wrapping in a try & catch. + try { + $this->getSession()->getDriver()->getWebDriverSession()->accept_alert(); + } catch (Exception $e) { + // Catching the generic one as we never know how drivers reacts here. + } + } catch (Exception $e) { + self::$currentstepexception = $e; + } } /** @@ -258,9 +299,10 @@ class behat_hooks extends behat_base { // No javascript is running if there is no window right? $pending = ''; } catch (UnknownError $e) { - // Same exception as before, but some combinations of browser + OS reports it as an unknown error - // exception. - $pending = ''; + // M is not defined when the window or the frame don't exist anymore. + if (strstr($e->getMessage(), 'M is not defined') != false) { + $pending = ''; + } } // If there are no pending JS we stop waiting. @@ -284,10 +326,16 @@ class behat_hooks extends behat_base { * after each step so no features will splicitly use it. * * @Given /^I look for exceptions$/ + * @throw Exception Unknown type, depending on what we caught in the hook or basic \Exception. * @see Moodle\BehatExtension\Tester\MoodleStepTester */ public function i_look_for_exceptions() { + // If the step already failed in a hook throw the exception. + if (!is_null(self::$currentstepexception)) { + throw self::$currentstepexception; + } + // Wrap in try in case we were interacting with a closed window. try { diff --git a/mod/scorm/tests/behat/add_scorm.feature b/mod/scorm/tests/behat/add_scorm.feature index e9480c94480..57cb932eeb8 100644 --- a/mod/scorm/tests/behat/add_scorm.feature +++ b/mod/scorm/tests/behat/add_scorm.feature @@ -39,3 +39,4 @@ Feature: Add scorm activity And I switch to "contentFrame" iframe And I should see "Play of the game" And I switch to the main frame + And I follow "Course 1"