/** * Take a screenshot and save html when step fails. Works only with Selenium2Driver. * * @AfterStep * @param AfterStepScope $scope */ public function takeScreenshotAfterFailedStep(Behat\Behat\Hook\Scope\AfterStepScope $scope) { if (99 === $scope->getTestResult()->getResultCode()) { $this->debugger->getScreenshot($scope); $this->debugger->saveHtml($scope); } }
/** * This hook should be placed in all contexts to allow easy debug on Travis CI * @AfterStep * @param AfterStepScope $event */ public function outputHtmlAfterFailedStep(AfterStepScope $event) { if (!$event->getTestResult()->isPassed()) { if ($this->getSession()->getDriver() instanceof \Behat\Mink\Driver\Selenium2Driver) { var_dump($this->getSession()->getCurrentUrl()); var_dump($this->getSession()->getPage()->getHtml()); } } }
/** * @AfterStep */ public function afterStep(AfterStepScope $scope) { if ($scope->getTestResult()->getResultCode() == TestResult::FAILED) { $file = sprintf('%s/storage/app/%d.jpg', getcwd(), time()); file_put_contents($file, $this->getSession()->getDriver()->getScreenshot()); // to do: get information from current step and build a message out of it $this->slack->error('Error', $file); } }
/** * Take screenshot when step fails. Works only with Selenium2Driver. * Screenshot is saved at [Date]/[Feature]/[Scenario]/[Step].jpg * @AfterStep */ public function after(AfterStepScope $scope) { if ($scope->getTestResult()->getResultCode() === 99) { $driver = $this->getSession()->getDriver(); if ($driver instanceof Behat\Mink\Driver\Selenium2Driver) { $fileName = date('d-m-y') . '-' . uniqid() . '.png'; $this->saveScreenshot($fileName, $this->screenshot_dir); print 'Screenshot at: ' . $this->screenshot_dir . '/' . $fileName; } } }
/** * @AfterStep */ public function failScreenshots(AfterStepScope $scope) { if (!$scope->getTestResult()->isPassed()) { $scenario = $this->getScenario($scope); if ($scenario->hasTag('javascript')) { $scenarioName = urlencode(str_replace(' ', '_', $scope->getSuite()->getName())); $filename = sprintf('fail_%s_%s.png', time(), $scenarioName); $this->saveScreenshot($filename, $this->screenshotDir); } } }
/** Write a html dump after a failing step. * * @AfterStep */ public function dumpPageAfterFailedStep(AfterStepScope $event) { if ($event->getTestResult() instanceof ExecutedStepResult && !$event->getTestResult()->isPassed()) { if (!is_dir($this->htmlDumpPath)) { mkdir($this->htmlDumpPath, 0755, true); } $minkContext = $event->getEnvironment()->getContext($this->contextName); if (!$minkContext) { return; } $filePath = $this->htmlDumpPath . '/' . date('Y-m-d-H-i-s') . '_' . uniqid() . '.html'; file_put_contents($filePath, "<!-- HTML dump from behat\nDate: " . date('Y-m-d H:i:s') . "\nUrl: " . $minkContext->getSession()->getCurrentUrl() . "\n-->\n" . $minkContext->getSession()->getPage()->getContent()); $message = "\nHTML saved to: file://" . $filePath; $exception = $event->getTestResult()->getException(); $refObj = new ReflectionObject($exception); $refObjProp = $refObj->getProperty('message'); $refObjProp->setAccessible(true); $refObjProp->setValue($exception, $exception->getMessage() . $message); } }
/** * @AfterStep */ function showRecentPlaceholders(AfterStepScope $scope) { if ($scope->getTestResult()->getResultCode() == TestResult::FAILED) { if (!empty($this->placeholders)) { echo "\nPlaceholders:"; foreach ($this->placeholders as $name => $value) { echo sprintf("\n %s: %s", $name, $value); } echo "\n\n"; } } }
/** * Take screenshot and Captures the HTML when step fails. * Works only with Selenium2Driver. * * @AfterStep */ public function dumpAssetsAfterFailedStep(AfterStepScope $scope) { if (99 === $scope->getTestResult()->getResultCode()) { // Only attempt to grab assets if we're at a url. if ($this->printUrl()) { $this->grabScreenshot(); // Dump the html. $this->grabHtml(); } // Log the watchdog //$this->dumpAsset('watchdog exception', $event->getStep()->getText() , 'log', $this->getWatchdog()); } }
/** * Take screenshot when step fails. * Works only with Selenium2Driver. * * @AfterStep */ public function takeScreenshotAfterFailedStep(AfterStepScope $event) { if (0 !== $event->getTestResult()->getResultCode()) { $driver = $this->getSession()->getDriver(); if (!$driver instanceof Selenium2Driver) { //throw new UnsupportedDriverActionException('Taking screenshots is not supported by %s, use Selenium2Driver instead.', $driver); return; } $screenshot = $this->getSession()->getDriver()->getScreenshot(); $lineNumber = $event->getStep()->getLine(); list($feature, $extension) = explode('.', substr($event->getFeature()->getFile(), strrpos($event->getFeature()->getFile(), '/') + 1)); file_put_contents('tests/acceptance/_logs/screenshots/' . $feature . '-line-' . $lineNumber . '-failure.png', $screenshot); } }
/** * Take screen-shot when step fails. Works only with Selenium2Driver. * * @AfterStep * @param AfterStepScope $scope */ public function takeScreenshotAfterFailedStep(AfterStepScope $scope) { if (99 === $scope->getTestResult()->getResultCode()) { $driver = $this->getSession()->getDriver(); if (!$driver instanceof Selenium2Driver) { return; } if (!is_dir($this->screenShotPath)) { mkdir($this->screenShotPath, 0777, true); } $filename = sprintf('%s_%s_%s.%s', $this->getMinkParameter('browser_name'), date('Ymd') . '-' . date('His'), uniqid('', true), 'png'); $this->saveScreenshot($filename, $this->screenShotPath); } }
/** * @AfterStep */ public function dumpInfoAfterFailedStep(AfterStepScope $scope) { if ($scope->getTestResult()->getResultCode() === TestResult::FAILED) { $driver = $this->getSession()->getDriver(); if (!$driver instanceof Selenium2Driver) { return; } $baseUrl = $this->getMinkParameter('base_url'); $fileName = date('d-m-y') . '-' . uniqid() . '.png'; $filePath = $this->getContainer()->get('kernel')->getRootdir() . '/../web/tmp/'; $this->saveScreenshot($fileName, $filePath); print 'Screenshot at: ' . $baseUrl . 'tmp/' . $fileName; $this->iPutABreakpoint(); } }
/** * @AfterStep */ public function takeScreenShotAfterFailedStep(AfterStepScope $scope) { if (TestResult::FAILED === $scope->getTestResult()->getResultCode()) { $driver = $this->getSession()->getDriver(); if (!$driver instanceof Selenium2Driver) { return; } // Create unique folder for this inspection $artifactsPath = '~/artifacts/' . date('YmdHis') . '/'; if (!file_exists($artifactsPath)) { mkdir($artifactsPath, 0777, true); } // Create screenshot file_put_contents('~/artifacts/' . uniqid() . '.png', $this->getSession()->getDriver()->getScreenshot()); } }
/** * Send an email to the team after step failed with error message, screen, and generated html. * * @AfterStep */ public function dumpInfoAfterFailedStep(AfterStepScope $scope) { if ($scope->getTestResult()->getResultCode() === StepResult::FAILED && null !== $this->getScenario($scope)) { $error = nl2br($scope->getStep()->getText()) . '<br /><br /><b style="color: red">Failed with message : ' . $scope->getTestResult()->getException()->getMessage() . '</b><br />'; $message = \Swift_Message::newInstance()->setFrom('*****@*****.**')->setTo('*****@*****.**')->setSubject('Error on scenario: ' . $this->getScenario($scope)->getTitle()); if ($this->minkContext->getSession()->getDriver() instanceof \Behat\Mink\Driver\Selenium2Driver) { $screenshot = $this->minkContext->getSession()->getDriver()->getScreenshot(); $message->attach(\Swift_Attachment::newInstance($screenshot, 'screenshot.png', 'image/png')); } $error .= '<br /><br />Driver: "' . get_class($this->minkContext->getSession()->getDriver()) . '"'; $message->attach(\Swift_Attachment::newInstance($this->minkContext->getSession()->getPage()->getHtml(), 'page.html', 'text/html')); $message->setBody('<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body>' . $error . '</body></html>', 'text/html'); $transport = \Swift_SmtpTransport::newInstance('smtp.mailgun.org', 587)->setUsername('*****@*****.**')->setPassword($this->getSmtpPassword()); $mailer = \Swift_Mailer::newInstance($transport); $mailer->send($message); } }
/** * Optionally (based on config) saves screenshot after every (failed) step. * * @AfterStep */ public function takeScreenshotAfterFailedStep(AfterStepScope $scope) { $after_fail = $this->parameters['enabled_on_fail']; $always = $this->parameters['enabled_always']; if ($always || $after_fail && 99 === $scope->getTestResult()->getResultCode()) { $filename = date('d-m-y') . '-' . uniqid() . '.png'; $location = $this->parameters['screenshot_path']; $location = $location ?: '/tmp'; try { $screenshot = $this->getSession()->getDriver()->getScreenshot(); file_put_contents($location . '/' . $filename, $screenshot); print 'Screenshot at: ' . $location . '/' . $filename; } catch (UnsupportedDriverActionException $e) { print $e->getMessage(); } } }
/** * @AfterStep */ public function showLastResponse(AfterStepScope $scope) { if ($scope->getTestResult()->getResultCode() == TestResult::FAILED) { if ($response = $this->client->getResponse()) { if ($response instanceof StreamedResponse) { echo "\nLast response status: {$response->getStatusCode()}, content is a STREAM, cannot dump it..\n\n"; } else { $body = $response->getContent(); $json = json_decode($body, true); if ($json !== null) { $body = json_encode($json, JSON_PRETTY_PRINT); } echo "\nLast response status: {$response->getStatusCode()}, content:\n\n"; echo "\n{$body}\n\n"; } } } }
/** * If using the Selenium2Driver, will automatically screenshot any failed * steps and save them in the current directory. * * Screenshots are named as "step-<step-line-number>-<timestamp>.png". * * @AfterStep * @param AfterStepScope $event */ public function takeScreenshotAfterFailedStep(AfterStepScope $event) { if (!$event->getTestResult()->isPassed()) { if ($this->getSession()->getDriver() instanceof Selenium2Driver) { $stepLine = $event->getStep()->getLine(); $time = time(); $fileName = "./step-{$stepLine}-{$time}.png"; if (is_writable('.')) { $screenshot = $this->getSession()->getDriver()->getScreenshot(); $stepText = $event->getStep()->getText(); if (file_put_contents($fileName, $screenshot)) { echo "Screenshot for '{$stepText}' placed in {$fileName}" . PHP_EOL; } else { echo "Screenshot failed: {$fileName} is not writable."; } } } } }
public function saveHtml(Behat\Behat\Hook\Scope\AfterStepScope $scope) { if (!$scope->getTestResult()->isPassed()) { $session = $this->featureContext->getSession(); $page = $session->getPage(); $fileName = str_replace(array(' ', ','), '-', $scope->getFeature()->getTitle()); if (!file_exists($this->html_dump_path)) { mkdir($this->html_dump_path); } $date = date('Y-m-d H:i:s'); $url = $session->getCurrentUrl(); $html = $page->getContent(); $html = "<!-- HTML dump from behat \nDate: {$date} \nUrl: {$url} -->\n " . $html; $htmlCapturePath = $this->html_dump_path . '/' . $fileName . '.html'; file_put_contents($htmlCapturePath, $html); $message = "\nHTML saved to: " . $this->html_dump_path . "/" . $fileName . ".html"; $message .= "\nHTML available at: " . $this->html_dump_url . "/" . $fileName . ".html"; echo $message; } }
/** * Take screen shot when step fails. * And then pause everything * Works only with Selenium2Driver. * * @param AfterStepScope $scope * * @AfterStep */ public function myAfterStepHook(AfterStepScope $scope) { if (99 === $scope->getTestResult()->getResultCode()) { $driver = $this->getSession()->getDriver(); if ($driver instanceof \Behat\Mink\Driver\Selenium2Driver) { $name = preg_replace('%[^a-z0-9]%i', '_', array_pop($_SERVER['argv']) . ':' . $scope->getStep()->getText() . '_' . $driver->getCurrentUrl()); if (!file_exists('/tmp/behat')) { mkdir('/tmp/behat/'); } if (strlen($name) > 250) { $name = substr($name, 0, 200); $name .= date('YmdHis'); } $file = '/tmp/behat/' . $name . '.png'; file_put_contents($file, $this->getSession()->getDriver()->getScreenshot()); echo "Error Screen Shot Saved to {$file}"; xdebug_break(); } } }
/** * @AfterStep */ public function failScreenshots(AfterStepScope $scope) { if (!$scope->getTestResult()->isPassed()) { $makeScreenshot = false; $suiteName = urlencode(str_replace(' ', '_', $scope->getSuite()->getName())); $featureName = urlencode(str_replace(' ', '_', $scope->getFeature()->getTitle())); if ($background = $this->getBackground($scope)) { $makeScreenshot = $scope->getFeature()->hasTag('javascript'); $scenarioName = 'background'; } else { $scenario = $this->getScenario($scope); $makeScreenshot = $scope->getFeature()->hasTag('javascript') || $scenario->hasTag('javascript'); $scenarioName = urlencode(str_replace(' ', '_', $scenario->getTitle())); } if ($makeScreenshot) { $filename = sprintf('fail_%s_%s_%s.png', time(), $suiteName, $featureName, $scenarioName); $this->saveScreenshot($filename, $this->screenshotDir); } } }
/** * Wait for JS to complete after finishing the step. * * With this we ensure that there are not AJAX calls * still in progress. * * 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. * * @param AfterStepScope $scope scope passed by event fired after step.. * @AfterStep */ public function after_step_javascript(AfterStepScope $scope) { global $CFG, $DB; // Save the page content if the step failed. if (!empty($CFG->behat_faildump_path) && $scope->getTestResult()->getResultCode() === Behat\Testwork\Tester\Result\TestResult::FAILED) { $this->take_contentdump($scope); } // Abort any open transactions to prevent subsequent tests hanging. // This does the same as abort_all_db_transactions(), but doesn't call error_log() as we don't // want to see a message in the behat output. if ($scope->getTestResult() instanceof \Behat\Behat\Tester\Result\ExecutedStepResult && $scope->getTestResult()->hasException()) { if ($DB && $DB->is_transaction_started()) { $DB->force_transaction_rollback(); } } // Only run if JS. if (!$this->running_javascript()) { return; } // Save a screenshot if the step failed. if (!empty($CFG->behat_faildump_path) && $scope->getTestResult()->getResultCode() === Behat\Testwork\Tester\Result\TestResult::FAILED) { $this->take_screenshot($scope); } 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; } }
/** * @AfterStep * * @param AfterStepScope $scope */ public function printResponse(AfterStepScope $scope) { if (!$scope->getTestResult()->isPassed() && $this->webApiContext->getRequest() && $this->webApiContext->getResponse()) { $this->webApiContext->printResponse(); } }
/** * @AfterStep I am logged in as */ public function storeUser(AfterStepScope $afterStepScope) { $this->user = $afterStepScope->getTestResult()->getCallResult()->getReturn(); }
/** * @AfterStep */ public function failScreenshots(AfterStepScope $scope) { if ($this->getSession()->getDriver() instanceof Selenium2Driver) { if (!$scope->getTestResult()->isPassed() && property_exists($this, "screenshots")) { if ($this->screenshots->onfail == true) { $scenarioLine = str_replace(' ', '_', $scope->getStep()->getLine()); $filename = sprintf('fail_on_line_%s_%s.png', $scenarioLine, date('H-i-s')); $this->makeScreenshot($filename); } } } }
/** * Take screen shot when step fails. * And then pause everything * Works only with Selenium2Driver. * * @param \Behat\Behat\Hook\Scope\AfterStepScope $scope * */ protected function screenShotFailedSteps(\Behat\Behat\Hook\Scope\AfterStepScope $scope, $caught = false) { if (99 === $scope->getTestResult()->getResultCode() || $caught) { $driver = $this->getSession()->getDriver(); if ($driver instanceof \Behat\Mink\Driver\Selenium2Driver) { $name = substr(preg_replace('%[^a-z0-9]%i', '_', array_pop($_SERVER['argv']) . ':' . $scope->getStep()->getText() . '_' . $driver->getCurrentUrl()), 0, 100); $file = '/tmp/behat_' . $name . '.png'; file_put_contents($file, $this->getSession()->getDriver()->getScreenshot()); echo "\n( Error Screen Shot Saved to {$file})\n\n"; } } }
/** * @AfterStep * * Take screenshot when step fails. */ public function takeScreenshotAfterFailedStep(AfterStepScope $scope) { if (self::ERROR_CODE === $scope->getTestResult()->getResultCode()) { $driver = $this->getSession()->getDriver(); // Get the text of the failed step. $failed_test_step = $scope->getStep()->getText(); // Remove quotes from the test step name. $failed_test_step = str_replace('"', '', $failed_test_step); // Set the screenshot location $filePath = $this->parameters['screenshots']; if ($driver instanceof \Behat\Mink\Driver\BrowserKitDriver) { $html_data = $this->getSession()->getDriver()->getContent(); $fileName = date(self::DATE_FORMAT_CONCISE) . '-' . $failed_test_step . '.html'; file_put_contents($filePath . '/' . $fileName, $html_data); return; } if ($driver instanceof \Behat\Mink\Driver\Selenium2Driver) { $fileName = date(self::DATE_FORMAT_CONCISE) . '-' . $failed_test_step . '.jpg'; $this->saveScreenshot($fileName, $filePath); return; } } }
/** * Take screenshot when step fails. * Works only with Selenium2Driver. * * @AfterStep */ public function takeScreenshotAfterFailedStep(AfterStepScope $scope) { if (!$scope->getTestResult()->isPassed()) { $driver = $this->getSession()->getDriver(); if (!$driver instanceof Selenium2Driver) { //throw new UnsupportedDriverActionException('Taking screenshots is not supported by %s, use Selenium2Driver instead.', $driver); return; } $step = $scope->getStep(); $step_line = $step->getLine(); $temp_path = $this->getContextParameter('temp_path'); $filename = $temp_path . '/stepAtLine' . $step_line . '.png'; $screenshot = $driver->getWebDriverSession()->screenshot(); file_put_contents($filename, base64_decode($screenshot)); echo "Saved Screenshot To {$filename} \n"; $filename = $temp_path . '/stepAtLine' . $step_line . '.html'; $source = $driver->getWebDriverSession()->source(); file_put_contents($filename, $source); echo "Saved Source To {$filename}\n"; } }
/** * @AfterStep * * @param AfterStepScope $scope */ public function takeScreenshotAfterFailedStep(AfterStepScope $scope) { if (99 === $scope->getTestResult()->getResultCode()) { $this->takeScreenshot(); } }
/** * @AfterStep * * Take screenshot and HTML dump when test fails. */ public function captureScreenAfterFailedStep(AfterStepScope $scope) { if (self::ERROR_CODE !== $scope->getTestResult()->getResultCode()) { return; } // Remove quotes from the test step name. $failed_test_step = preg_replace('/[^a-zA-Z0-9\\-]+/', '_', $scope->getStep()->getText()); // Set the screenshot location. $featureFolder = str_replace(' ', '', $scope->getFeature()->getTitle()); $filePath = $this->parameters['screenshot_path'] . '/' . $featureFolder; if (!file_exists($filePath)) { mkdir($filePath); } $driver = $this->getSession()->getDriver(); $filename_prefix = date(self::DATE_FORMAT_CONCISE) . '-' . $failed_test_step; if ($driver instanceof \Behat\Mink\Driver\BrowserKitDriver) { // Generate HTML dump. $html_data = $this->getSession()->getDriver()->getContent(); $fileName = $filename_prefix . self::EXTENSION_DOT . self::EXTENSION_HTML; file_put_contents($filePath . '/' . $fileName, $html_data); } elseif ($driver instanceof \Behat\Mink\Driver\Selenium2Driver) { // Generate HTML dump. $html_data = $this->getSession()->getDriver()->getContent(); $fileName = $filename_prefix . self::EXTENSION_DOT . self::EXTENSION_HTML; file_put_contents($filePath . '/' . $fileName, $html_data); // Generate JPG. $fileName = $filename_prefix . self::EXTENSION_DOT . self::EXTENSION_JPG; $this->saveScreenshot($fileName, $filePath); } }
/** * @AfterStep * * @param $event */ public function showError(AfterStepScope $event) { if (!$event->getTestResult()->isPassed()) { print "Ruta: " . $this->getSession()->getCurrentUrl() . "\n"; } }
/** * Take screenshot when step fails. Works only with Selenium2Driver. * * @AfterStep * @param AfterStepScope $scope */ public function takeScreenshotAfterFailedStep(AfterStepScope $scope) { if (TestResult::FAILED === $scope->getTestResult()->getResultCode()) { $this->takeScreenshot(); $this->logRequest(); } }