Rob Gudgeon Rob Gudgeon - 4 months ago 44
PHP Question

phpunit & php-webdriver sharing a webdriver instance

I'm trying to figure out how to share a single php-webdriver instance across multiple phpunit tests. The instance works fine for the first test but by the second test the driver's executor's curl resource has been lost.

setup-webdriver.php:

<?php

namespace Facebook\WebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
require_once('php-webdriver-community/vendor/autoload.php');

$host = 'http://localhost:4444/wd/hub';
$capabilities = DesiredCapabilities::firefox();
$driver = RemoteWebDriver::create($host, $capabilities, 5000);


tests/GoogleTest.php:

<?php

class GoogleTest extends PHPUnit_Framework_TestCase {

public function testGoogleTitle() {

global $driver;
print_r($driver);
$driver->get('http://www.google.com/');
echo $driver->getTitle();
}
}


tests/YahooTest.php:

<?php

class YahooTest extends PHPUnit_Framework_TestCase {

public function testYahooTitle()
{
global $driver;
print_r($driver);
$driver->get('http://www.yahoo.com/');
echo $driver->getTitle();
}
}


I'm running it via
/opt/local/bin/php56 /usr/local/bin/phpunit-5.1 --bootstrap setup-webdriver.php tests


The Google test runs first, and works fine, but by the time the Yahoo test runs, it exits with

1) YahooTest::testYahooTitle
curl_setopt() expects parameter 1 to be resource, integer given


The full output is:

PHPUnit 5.1.2 by Sebastian Bergmann and contributors.

.Facebook\WebDriver\Remote\RemoteWebDriver Object
(
[executor:protected] => Facebook\WebDriver\Remote\HttpCommandExecutor Object
(
[url:protected] => http://localhost:4444/wd/hub
[curl:protected] => Resource id #1007
)

[sessionID:protected] => 7b2577fa-98f1-4f75-9b18-a22a0b7474eb
[mouse:protected] =>
[keyboard:protected] =>
[touch:protected] =>
[executeMethod:protected] =>
)
GoogleE 2 / 2 (100%)Facebook\WebDriver\Remote\RemoteWebDriver Object
(
[executor:protected] => Facebook\WebDriver\Remote\HttpCommandExecutor Object
(
[url:protected] => http://localhost:4444/wd/hub
[curl:protected] => 0
)

[sessionID:protected] => 7b2577fa-98f1-4f75-9b18-a22a0b7474eb
[mouse:protected] =>
[keyboard:protected] =>
[touch:protected] =>
[executeMethod:protected] =>
)


Time: 2.67 seconds, Memory: 11.00Mb

There was 1 error:

1) YahooTest::testYahooTitle
curl_setopt() expects parameter 1 to be resource, integer given


/Users/robgudgeon/Downloads/code/phpunit-a-test/php-webdriver-community/lib/Remote/HttpCommandExecutor.php:227
/Users/robgudgeon/Downloads/code/phpunit-a-test/php-webdriver-community/lib/Remote/RemoteWebDriver.php:507
/Users/robgudgeon/Downloads/code/phpunit-a-test/php-webdriver-community/lib/Remote/RemoteWebDriver.php:187
/Users/robgudgeon/Downloads/code/phpunit-a-test/tests/YahooTest.php:9

FAILURES!
Tests: 2, Assertions: 0, Errors: 1.


I only added the calls to
print_r($driver)
to try to figure out the reason for the error & it's obviously because the curl resource has changed from being a valid resource for the Google test, to being 0 by the time of the Yahoo test.

The reason for setting this up is that I have a full working test suite (for a work project) but currently it runs around 50 tests in a single script, and I'm trying to figure out how to split the tests into logical groups/files, whilst sharing the same webdriver instance - it seemed to me that the best way was to use the bootstrap file to set up the webdriver & then re-use it. The code I've shown is just a proof-of-concept, I'm well aware that calling print_r(), echo etc. within phpunit tests isn't the correct way to test things, I'm just trying to learn & understand how to achieve this.

Answer

First of all, don't use globals, use the fixtures available in PHPUnit

class BaseTestCase extends PHPUnit_Framework_TestCase
{
    static $driver;

    public static function setUpBeforeClass()
    {

        $host = 'http://localhost:4444/wd/hub';
        $capabilities = DesiredCapabilities::firefox();
        self::$driver = RemoteWebDriver::create($host, $capabilities, 5000);
    }

    public static function tearDownAfterClass()
    {

        self::$driver->close();
    }

    public function getDriver()
    {
        return self::$driver;
    }
}

class GoogleTest extends BaseTestCase
{

    public function setUp()
    {
        $this->getDriver()->get('http://www.google.com/');
    }

    public function testTitle()
    {

        echo $this->getDriver()->getTitle();
    }

    public function testSomethingElse()
    {
        // do test
    }
}


class YahooTest extends BaseTestCase
{

    public function testYahooTitle()
    {
        $this->getDriver()->get('http://www.yahoo.com/');
        echo $this->getDriver()->getTitle();
    }
}

This example won't share the same $driver between both GoogleTest and YahooTest but that is recommended as you will want a clean slate for each test.

However all the tests in GoogleTest will share the same driver. The execution order of tests, when you do 'phpunit tests' will be:

setUpBeforeClass() 

setUp()
testTitle()

setUp()
testSomethingElse()

tearDownAfterClass() 

I recommend reading a bit more about fixtures

Comments