Behat 3: Taking screenshots after failed steps

Created on 21 Oct 2014  路  8Comments  路  Source: Behat/Behat

Code below works fine for Behat 2 but it doesn't for Behat 3. Does anyone know how to implement it in Behat 3?

_Behat 3 error:_

PHP Fatal error:  Call to undefined method Behat\Behat\Hook\Scope\AfterStepScope::getResult() in behat-three/features/bootstrap/Site/MainBundle/Features/Context/FeatureContext.php on line 65

Line 65 is : if (4 === $event->getResult()) {

_Behat 2 working example_

namespace Site\CommonBundle\Features\Context;

use Behat\MinkExtension\Context\MinkContext;
use Behat\Mink\Exception\UnsupportedDriverActionException;
use Behat\Mink\Driver\Selenium2Driver;
use Behat\Symfony2Extension\Context\KernelAwareInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Process\Process;

class FeatureContext extends MinkContext implements KernelAwareInterface
{
    /**
     * Take screen-shot when step fails. Works only with Selenium2Driver.
     *
     * @AfterStep
     * @param $event Current event.
     * @throws \Behat\Mink\Exception\UnsupportedDriverActionException
     */
    public function takeScreenshotAfterFailedStep($event)
    {
        if (4 === $event->getResult()) {
            $driver = $this->getSession()->getDriver();

            if (! ($driver instanceof Selenium2Driver)) {
                throw new UnsupportedDriverActionException(
                    'Taking screen-shots is not supported by %s, use Selenium2Driver instead.',
                    $driver
                );

                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'
            );

            file_put_contents($this->screenShotPath . '/' . $filename, $driver->getScreenshot());
        }
    }
}

Most helpful comment

    /**
     * @AfterStep
     */
    public function takeScreenshotAfterFailedStep(AfterStepScope $scope)
    {
        if (99 === $scope->getTestResult()->getResultCode()) {
            $this->takeScreenshot();
        }
    }

    private function takeScreenshot()
    {
        $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;
    }

Something like that works

All 8 comments

    /**
     * @AfterStep
     */
    public function takeScreenshotAfterFailedStep(AfterStepScope $scope)
    {
        if (99 === $scope->getTestResult()->getResultCode()) {
            $this->takeScreenshot();
        }
    }

    private function takeScreenshot()
    {
        $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;
    }

Something like that works

That worked well. Thanks.

Not working for me undefined method getContainer(), which lib did you use? (behat 3)

@narozhniyy If you can wait a bit, I'll give you full example however while waiting, do research on how to use container in FeatureContext files. There are many examples so you might solve your problem yourself.

@BentCoder it's will be great, thanks

@BentCoder did you forget about me?

@narozhniyy No I didn't! There seem to be a problem with the library I think because what was working before doesn't want to work anymore hence reason I left a message here https://github.com/Behat/Behat/issues/764 but no one got back to me yet. Keep an eye on that issue. Let's wait what they say.

OK work now!

composer.json

    "require-dev": {
        "behat/behat" : "3.0.15",
        "behat/symfony2-extension" : "2.0.0",
        "behat/mink": "1.6.1",
        "behat/mink-extension": "2.0.1",
        "behat/mink-browserkit-driver": "1.2.0",
        "behat/mink-goutte-driver": "1.1.0",
        "behat/mink-selenium2-driver": "1.2.0"
    },

behat.yml

default:
    extensions:
        Behat\Symfony2Extension: ~
        Behat\MinkExtension:
            base_url: http://football.local/app_test.php
            browser_name: firefox
            sessions:
                goutte:
                    goutte: ~
                selenium2:
                    selenium2: ~
                symfony2:
                    symfony2: ~
    suites:
        backend:
            type: symfony_bundle
            bundle: ApplicationBackendBundle
            mink_session: selenium2
            contexts:
                - Application\BackendBundle\Features\Context\FeatureContext:
                    screen_shot_path: build/phing/behat/screenshot

FeatureContext

namespace Application\BackendBundle\Features\Context;

use Behat\Behat\Hook\Scope\AfterStepScope;
use Behat\Mink\Driver\Selenium2Driver;
use Behat\MinkExtension\Context\MinkContext;

class FeatureContext extends MinkContext
{
    private $screenShotPath;

    public function __construct($screen_shot_path)
    {
        $this->screenShotPath = $screen_shot_path;
    }

    /**
     * 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);
        }
    }
}

example feature

Feature: Dummy feature

  Scenario: Home url
    Given I am on "/backend"
    Then I should see "Welcome to Application backend! I will break this test"

Download and run selenium first
First download it (version 2.46.0) and put right into your project folder. http://www.seleniumhq.org/download/

Bc-MBP:football bentcoder$ java -jar selenium-server-standalone-2.46.0.jar

Run test

Bc-MBP:football bentcoder$  bin/behat --suite=backend
Feature: Dummy feature

  Scenario: Home url                                     # src/Application/BackendBundle/Features/Dummy.feature:3
    Given I am on "/backend"                             # Application\BackendBundle\Features\Context\FeatureContext::visit()
    Then I should see "Welcome to Application backend! I will break this test" # Application\BackendBundle\Features\Context\FeatureContext::assertPageContainsText()
      The text "Welcome to Application backend!1" was not found anywhere in the text of the current page. (Behat\Mink\Exception\ResponseTextException)

--- Failed scenarios:

    src/Application/BackendBundle/Features/Dummy.feature:3

1 scenario (1 failed)
2 steps (1 passed, 1 failed)

project folder structure for screenshots

   build
      phing
         behat
            screenshots

result

image

Was this page helpful?
0 / 5 - 0 ratings