/** * 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); } }
/** * @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 current page screenshot and save it to path * * @AfterStep * * @param AfterStepScope $scope afterStep scope object * * @return null */ public function takeScreenshot(AfterStepScope $scope) { $featureFilePath = $scope->getFeature()->getFile(); $stepLineNumber = $scope->getStep()->getLine(); $screenshotPath = $this->createScreenshotFilePath($featureFilePath, $stepLineNumber); $driver = $this->getSession()->getDriver(); $imageData = $driver->getScreenshot(); file_put_contents($screenshotPath, $imageData); }
/** * 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()); } } }
/** * 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; } } }
/** * @param AfterStepScope $scope * @return \Behat\Gherkin\Node\ScenarioInterface|null */ private function getScenario(AfterStepScope $scope) { $scenarios = $scope->getFeature()->getScenarios(); $stepLine = $scope->getStep()->getLine(); $scenario = null; foreach ($scenarios as $scenarioTmp) { if ($scenarioTmp->getLine() < $stepLine) { $scenario = $scenarioTmp; } } return $scenario; }
/** * @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()); } }
/** * @param AfterStepScope $scope * @return \Behat\Gherkin\Node\ScenarioInterface */ private function getScenario(AfterStepScope $scope) { $scenarios = $scope->getFeature()->getScenarios(); foreach ($scenarios as $scenario) { $stepLinesInScenario = array_map(function (StepNode $step) { return $step->getLine(); }, $scenario->getSteps()); if (in_array($scope->getStep()->getLine(), $stepLinesInScenario)) { return $scenario; } } throw new \LogicException('Unable to find the scenario'); }
/** * 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); } }
/** * @param AfterStepScope $scope * @return \Behat\Gherkin\Node\BackgroundNode */ private function getBackground(AfterStepScope $scope) { $background = $scope->getFeature()->getBackground(); if (!$background) { return false; } $stepLinesInBackground = array_map(function (StepNode $step) { return $step->getLine(); }, $background->getSteps()); if (in_array($scope->getStep()->getLine(), $stepLinesInBackground)) { return $background; } return false; }
/** * 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 debugStepsAfter(AfterStepScope $scope) { // Tests tagged with @debugEach will perform each step and wait for [ENTER] to proceed. if ($this->scenario->hasTag('debugEach')) { $env = $scope->getEnvironment(); $drupalContext = $env->getContext('Drupal\\DrupalExtension\\Context\\DrupalContext'); $minkContext = $env->getContext('Drupal\\DrupalExtension\\Context\\MinkContext'); // Print the current URL. try { $minkContext->printCurrentUrl(); } catch (Behat\Mink\Exception\DriverException $e) { print "No Url"; } $drupalContext->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()); } }
/** * 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."; } } } } }
/** * 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(); } } }
/** 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); } }
/** * Determine the full pathname to store a failure-related dump. * * This is used for content such as the DOM, and screenshots. * * @param AfterStepScope $scope scope passed by event after step. * @param String $filetype The file suffix to use. Limited to 4 chars. */ protected function get_faildump_filename(AfterStepScope $scope, $filetype) { global $CFG; // All the contentdumps should be in the same parent dir. if (!($faildumpdir = self::get_run_faildump_dir())) { $faildumpdir = self::$faildumpdirname = date('Ymd_His'); $dir = $CFG->behat_faildump_path . DIRECTORY_SEPARATOR . $faildumpdir; if (!is_dir($dir) && !mkdir($dir, $CFG->directorypermissions, true)) { // It shouldn't, we already checked that the directory is writable. throw new Exception('No directories can be created inside $CFG->behat_faildump_path, check the directory permissions.'); } } else { // We will always need to know the full path. $dir = $CFG->behat_faildump_path . DIRECTORY_SEPARATOR . $faildumpdir; } // The scenario title + the failed step text. // We want a i-am-the-scenario-title_i-am-the-failed-step.$filetype format. $filename = $scope->getFeature()->getTitle() . '_' . $scope->getStep()->getText(); $filename = preg_replace('/([^a-zA-Z0-9\\_]+)/', '-', $filename); // File name limited to 255 characters. Leaving 5 chars for line number and 4 chars for the file. // extension as we allow .png for images and .html for DOM contents. $filename = substr($filename, 0, 245) . '_' . $scope->getStep()->getLine() . '.' . $filetype; return array($dir, $filename); }
/** * @AfterStep * * @param AfterStepScope $scope */ public function printResponse(AfterStepScope $scope) { if (!$scope->getTestResult()->isPassed() && $this->webApiContext->getRequest() && $this->webApiContext->getResponse()) { $this->webApiContext->printResponse(); } }
/** * @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); } } } }
/** * @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; } } }
/** * @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(); } }
/** * 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"; } } }
/** * 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(); } }