Skip to content

Instantly share code, notes, and snippets.

@kerasai
Last active August 3, 2017 11:05
Show Gist options
  • Save kerasai/6c0066fa33d607fa798955e9dbc82211 to your computer and use it in GitHub Desktop.
Save kerasai/6c0066fa33d607fa798955e9dbc82211 to your computer and use it in GitHub Desktop.
Behat context for obtaining screenshots on step failure.
<?php
use Behat\Mink\Driver\Selenium2Driver;
use Behat\Behat\Hook\Scope\AfterStepScope;
use Behat\Mink\Mink;
use Behat\MinkExtension\Context\MinkAwareContext;
/**
* Class FailureContext.
*
* Saves markup (and screenshots for JS-enabled browsers) for failed steps. Also
* provides a step to take a screenshot during a test execution.
*
* Add to `behat.yml` with:
*
* @code
* - FailureContext:
* failure_path: '../failures'
* @endcode
*/
class FailureContext implements MinkAwareContext {
/**
* Where to write the failures.
*
* @var string
*/
protected $failurePath;
/**
* Mink parameters.
*
* @var \Behat\Mink\Mink
*/
protected $mink;
/**
* Mink instance.
*
* @var array
*/
protected $minkParameters = [];
/**
* FailureContext constructor.
*
* @param string $failure_path
* Where to write the failures.
*/
public function __construct($failure_path) {
$this->failurePath = $failure_path;
if (!file_exists($failure_path)) {
@mkdir($failure_path, 0755, TRUE);
}
}
/**
* Step for capturing a screenshot.
*
* @Then I take a screenshot
*/
public function assertScreenShot() {
$fileName = $this->failurePath . '/screenshot-' . date('Ymd_His');
$this->dumpMarkup($fileName);
$this->screenShot($fileName);
}
/**
* Analyzes the result of a step and performs dump/screenshot if failed.
*
* @param \Behat\Behat\Hook\Scope\AfterStepScope $scope
* The AfterStepScope for the failed step.
*
* @AfterStep
*/
public function handleFailure(AfterStepScope $scope) {
if (99 !== $scope->getTestResult()->getResultCode()) {
return;
}
$fileName = $this->fileName($scope);
$this->dumpMarkup($fileName);
$this->screenShot($fileName);
}
/**
* Compute a file name for a failed step output.
*
* @param \Behat\Behat\Hook\Scope\AfterStepScope $scope
* The AfterStepScope for the failed step.
*
* @return string
* The resulting filename including path.
*/
protected function fileName(AfterStepScope $scope) {
$baseName = pathinfo($scope->getFeature()->getFile());
$baseName = substr($baseName['basename'], 0, strlen($baseName['basename']) - strlen($baseName['extension']) - 1);
$baseName .= '-' . $scope->getStep()->getLine();
$baseName .= '-' . date('Ymd_His');
$baseName = $this->failurePath . '/' . $baseName;
return $baseName;
}
/**
* Save the markup from the failed step.
*
* @param string $fileName
* The full path and name of the file to write.
*/
protected function dumpMarkup($fileName) {
@mkdir($this->failurePath, 0755, TRUE);
$fileName .= '.html';
$html = $this->mink->getSession()->getPage()->getContent();
file_put_contents($fileName, $html);
sprintf("HTML available at: %s\n", $fileName);
}
/**
* Save a screen shot from the failed step.
*
* @param string $fileName
* The full path and name of the file to write.
*/
protected function screenShot($fileName) {
$fileName .= '.png';
$driver = $this->mink->getSession()->getDriver();
if ($driver instanceof Selenium2Driver) {
file_put_contents($fileName, $this->mink->getSession()->getDriver()->getScreenshot());
sprintf("Screen shot available at: %s\n", $fileName);
return;
}
}
/**
* {@inheritdoc}
*/
public function setMink(Mink $mink) {
$this->mink = $mink;
}
/**
* {@inheritdoc}
*/
public function setMinkParameters(array $parameters) {
$this->minkParameters = $parameters;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment