acfreitas
acfreitas

Reputation: 1397

How to capture a screenshot with PHPUnit and Selenium2 when the test fails?

I'm using PHPUnit 4.6 and PHPUnit Selenium 1.4.2 with PhantomJS. I want capture a screenshot with the last page when selenium test fails. In PHPUnit Manual there is a example for Selenium 1, but I'm trying use with Selenium 2, because I need use GhostDriver.

WebTestCase.php

class WebTestCase extends PHPUnit_Extensions_Selenium2TestCase
{
    protected $captureScreenshotOnFailure = TRUE;
    protected $screenshotPath = '/../../screenshots';
    protected $screenshotUrl = 'http://localhost:8080/screenshots';

    protected function setUp() {
        $this->setBrowser('phantomjs');
        $this->setBrowserUrl("http://localhost:8080");
        $this->setHost('localhost');
    }
}

Test.php

class Test extends WebTestCase
{

    public function testTitle()
    {
        $this->url('');
        assertEquals($this->title(), "My App");
    }
}

But this not capture a screenshot.

$ vendor/bin/phpunit 
PHPUnit 4.6-ge85198b by Sebastian Bergmann and contributors.

Configuration read from /MyApp/phpunit.xml

F

Time: 231 ms, Memory: 5.50Mb

There was 1 failure:

1) Test::testTitle
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-''
+'My App'

/MyApp/tests/functional/Test.php:7

FAILURES!                            
Tests: 1, Assertions: 1, Failures: 1.

Upvotes: 4

Views: 5131

Answers (4)

Silas Palmer
Silas Palmer

Reputation: 2985

Combining the solutions from @Jens A. Koch and @John Joseph, we get this:

<?php

class homepageTest extends PHPUnit_Extensions_Selenium2TestCase {

    private $listener;

    public function setUp() {

        // Your screenshots will be saved in '/var/www/vhosts/screenshots/'
        $screenshots_dir = '/var/www/vhosts/screenshots/';

        $this->listener = new PHPUnit_Extensions_Selenium2TestCase_ScreenshotListener($screenshots_dir);

        $this->setBrowser('firefox');
        $this->setBrowserUrl('https://netbeans.org');
    }

    public function testNetbeansContainsHorses() {
        $this->url('https://netbeans.org');
        $this->assertContains('Equestrian', $this->title()); // Will fail on NetBeans page.
    }


    public function onNotSuccessfulTest($e) {
        $this->listener->addError($this, $e, microtime(true));        
        parent::onNotSuccessfulTest($e);
    }
}

Upvotes: 6

Jens A. Koch
Jens A. Koch

Reputation: 41756

Hmm. The difference between SeleniumTestCase and Selenium2TestCase is not really good documented in the PHPUnit Manual. Also there is no clear separation and not enough usage examples for common cases on Selenium2.

$captureScreenshotOnFailure does not exist on PHPUnit_Extensions_Selenium2TestCase.

Anyway, let's try putting this together:

<?php
class Test extends PHPUnit_Extensions_Selenium2TestCase
{

    protected function setUp() {
        $this->setBrowser('phantomjs');
        $this->setBrowserUrl("http://localhost:8080");
        $this->setHost('localhost');
    }

    public function testEnterText()
    {
        $this->url("/");

        try {

            $this->assertEquals($this->title(), "My App");

        } catch (Exception $e) {

            $this->screenshot( __DIR__.'/'.$this->getName().'-'.time(). '.png');    
        }
    }

    public function screenshot($file) 
    {
        $filedata = $this->currentScreenshot();
        file_put_contents($file, $filedata);
    }
}

The try-catch-block: in the try part the assertion is done, if the assertion fails, the exception is caught. The catch-block gives us a chance to (grab details of the exception or re-throw it or) make a screenshot.

The main function is $this->currentScreenshot(), which was used in this test https://github.com/giorgiosironi/phpunit-selenium/blob/master/Tests/Selenium2TestCaseTest.php#L733

ScreenshotListener

Please note that there is a ScreenshotListener around, which might be worth looking at: https://github.com/giorgiosironi/phpunit-selenium/blob/master/PHPUnit/Extensions/Selenium2TestCase/ScreenshotListener.php

With usage example over at https://github.com/giorgiosironi/phpunit-selenium/blob/master/Tests/Selenium2TestCase/ScreenshotListenerTest.php

This might be a cleaner implementation to grab test failures and make shots.

Upvotes: 6

TestRunner
TestRunner

Reputation: 31

Use this to save screenshot..very useful in case of headless browser.

    $fp = fopen('path/35.png', 'wb');
    fwrite($fp, $this->currentScreenshot());
    fclose($fp);
    sleep(1);

Upvotes: 1

John Joseph
John Joseph

Reputation: 951

A way of doing this across all your web tests is to override one of the test failure functions from the parent test case class, and capture your screenshot there.

Example:

class MyBaseWebTests
{

    $this->directory = '/some_path_to_put_screenshots_in/';

    // Override PHPUnit_Extensions_Selenium2TestCase::onNotSuccessfulTest
    public function onNotSuccessfulTest(Exception $e)
    {
        $filedata   = $this->currentScreenshot();
        $file       = $this->directory . get_class($this) . '.png';
        file_put_contents($file, $filedata);

        parent::onNotSuccessfulTest($e);
    }
}

Now, after any of your web tests fail, they will dump a screenshot in that folder with the name of the web test class as the filename.

Upvotes: 2

Related Questions