keeping selenium browser open with phpunit/selenium

拈花ヽ惹草 提交于 2019-12-30 03:19:07

问题


when the tests fail, the browser that the selenium tests were running on closes. this is unhelpful when trying to debug. i know i have the option of a screen shot upon failure, but that doesn't help without the entire context. with the browser still available, i can hit back and inspect what was going on.

is there a way to keep the browser open even when asserts fail or elements aren't found?


回答1:


figured it out randomly many weeks later.

when starting the server, use the option -browserSessionReuse at the end. this will keep one browser session open throughout the tests and not close on failure




回答2:


You might be calling selenium.stop() at the end of the test. You need to comment out that line of code and make sure that your selenium object is not destroyed at the end of the test. This will keep the window open. Same question has been answered here




回答3:


Regarding the answer about -browserSessionReuse at https://stackoverflow.com/a/6904808/654026, keep in mind that you will have to deal with cleaning the cookies between tests executions. Otherwise you may have difficult to debug errors.




回答4:


A simple solution is to set the session $stopped property to true, in the test setUp() method. As the property is private, we need to use the Reflection api.

    function setUp() {

        ....

        // Set the private property $stopped of session to true, so the window is not closed on error or at the end of tests
        $myClassReflection = new \ReflectionClass( get_class( $this->prepareSession() ) );
        $secret            = $myClassReflection->getProperty( 'stopped' );
        $secret->setAccessible( true );
        $secret->setValue( $this->prepareSession(), true );

        ...
}



回答5:


After long hours of trying to create a relatively clean workaround, I now resorted to a very dirty, but very easy hack. The phpunit\selenium source code is not easy to override, it would have been nice if there had been factories used to create the Session objects. I tried to hack into the object creation by overriding and proxying objects, but still couldn't get it to work. Finally, I didn't want to spend more hours on this and went down the easiest and dirtiest path, i.e. hacked the code of the PHPUnit_Extensions_Selenium2TestCase_Session and PHPUnit_Extensions_Selenium2TestCase classes directly. In PHPUnit_Extensions_Selenium2TestCase inserted a static $_instance that can be used to check if there was a test failure condition. In PHPUnit_Extensions_Selenium2TestCase_Session intercepted the stop() method and queried the status of the TestCase. Works like a charm, but dirty dirty dirty.

PHPUnit_Extensions_Selenium2TestCase:

private static $_instance;
public static function getInstance() { return self::$_instance; }
....
public function __construct($name = NULL, array $data = array(), $dataName = '')
{
    self::$_instance = $this;
    ....
}

PHPUnit_Extensions_Selenium2TestCase_Session:

public function stop()
{
    if ($this->stopped || $this->hasFailedTests()) {
        return;
    }
    ....
}

private function hasFailedTests()
{
    $status = PHPUnit_Extensions_Selenium2TestCase::getInstance()->getStatus();
    return $status == \PHPUnit_Runner_BaseTestRunner::STATUS_ERROR
    || $status == \PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE;
}



回答6:


Here a cleaner solution. Overridden all classes involved with session creation. Session class is where the session is closed, so the stop() method needed to be overridden.

TODO: add parameters to control behaviour, if and when to keep browser window open or not.

Overridden 5 classes: PHPUnit_Extensions_Selenium2TestCase, PHPUnit_Extensions_Selenium2TestCase_Driver, PHPUnit_Extensions_Selenium2TestCase_Session, PHPUnit_Extensions_Selenium2TestCase_SessionStrategy_Isolated, PHPUnit_Extensions_Selenium2TestCase_SessionStrategy_Shared. Created 2 bootstrap files, 1 for shared browser sessions, 1 for isolated browser sessions. Showing 1 example test.

OkxSelenium2TestCase:

namespace OKInfoTech\PhpUnit\Selenium;

abstract class OkxSelenium2TestCase extends \PHPUnit_Extensions_Selenium2TestCase
{
    private static $_instance;
    public static function getInstance() { return self::$_instance; }

    public function __construct($name = NULL, array $data = array(), $dataName = '')
    {
        self::$_instance = $this;
        parent::__construct($name, $data, $dataName);

        $params = array(
            'host' => 'localhost',
            'port' => 4444,
            'browser' => NULL,
            'browserName' => NULL,
            'desiredCapabilities' => array(),
            'seleniumServerRequestsTimeout' => 60
        );
        $this->setUpSessionStrategy($params);
    }

    protected function setUpSessionStrategy($params)
    {
        parent::setUpSessionStrategy($params);
        if (isset($params['sessionStrategy'])) {
            $strat = $params['sessionStrategy'];
            switch ($strat) {
                case "isolated":
                    self::$browserSessionStrategy = new OkxSelenium2TestCase_SessionStrategy_Isolated;
                    break;
                case "shared":
                    self::$browserSessionStrategy = new OkxSelenium2TestCase_SessionStrategy_Shared(new OkxSelenium2TestCase_SessionStrategy_Isolated);
                    break;
            }
        } else {
            self::$browserSessionStrategy = new OkxSelenium2TestCase_SessionStrategy_Isolated;
        }
        $this->localSessionStrategy = self::$browserSessionStrategy;
    }
}

OkxSelenium2TestCase_Driver:

namespace OKInfoTech\PhpUnit\Selenium;

class OkxSelenium2TestCase_Driver extends \PHPUnit_Extensions_Selenium2TestCase_Driver
{
    private $seleniumServerUrl;
    private $seleniumServerRequestsTimeout;

    public function __construct(\PHPUnit_Extensions_Selenium2TestCase_URL $seleniumServerUrl, $timeout = 60)
    {
        $this->seleniumServerUrl = $seleniumServerUrl;
        $this->seleniumServerRequestsTimeout = $timeout;
        parent::__construct($seleniumServerUrl, $timeout);
    }

    public function startSession(array $desiredCapabilities, \PHPUnit_Extensions_Selenium2TestCase_URL $browserUrl)
    {
        $sessionCreation = $this->seleniumServerUrl->descend("/wd/hub/session");
        $response = $this->curl('POST', $sessionCreation, array(
            'desiredCapabilities' => $desiredCapabilities
        ));
        $sessionPrefix = $response->getURL();

        $timeouts = new \PHPUnit_Extensions_Selenium2TestCase_Session_Timeouts(
            $this,
            $sessionPrefix->descend('timeouts'),
            $this->seleniumServerRequestsTimeout * 1000
        );
        return new OkxSelenium2TestCase_Session(
            $this,
            $sessionPrefix,
            $browserUrl,
            $timeouts
        );
    }
}

OkxSelenium2TestCase_Session:

namespace OKInfoTech\PhpUnit\Selenium;

class OkxSelenium2TestCase_Session extends \PHPUnit_Extensions_Selenium2TestCase_Session
{
    public function stop()
    {
        if ($this->hasFailedTests()) {
            return;
        }
        parent::stop();
    }

    private function hasFailedTests()
    {
        $status = OkxSelenium2TestCase::getInstance()->getStatus();
        return $status == \PHPUnit_Runner_BaseTestRunner::STATUS_ERROR
        || $status == \PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE;
    }
}

OkxSelenium2TestCase_SessionStrategy_Isolated:

namespace OKInfoTech\PhpUnit\Selenium;

class OkxSelenium2TestCase_SessionStrategy_Isolated extends \PHPUnit_Extensions_Selenium2TestCase_SessionStrategy_Isolated
{
    public function session(array $parameters)
    {
        $seleniumServerUrl = \PHPUnit_Extensions_Selenium2TestCase_URL::fromHostAndPort($parameters['host'], $parameters['port']);
        $driver = new OkxSelenium2TestCase_Driver($seleniumServerUrl, $parameters['seleniumServerRequestsTimeout']);
        $capabilities = array_merge($parameters['desiredCapabilities'],
            array(
                'browserName' => $parameters['browserName']
            ));
        $session = $driver->startSession($capabilities, $parameters['browserUrl']);
        return $session;
    }
}

OkxSelenium2TestCase_SessionStrategy_Shared:

namespace OKInfoTech\PhpUnit\Selenium;

class OkxSelenium2TestCase_SessionStrategy_Shared extends \PHPUnit_Extensions_Selenium2TestCase_SessionStrategy_Shared
{

}

bootstrapIsolated.php:

require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';

spl_autoload_register(
    function ($class) {
        static $classes = NULL;
        static $path = NULL;

        if ($classes === NULL) {
            $classes = [
                'okinfotech\phpunit\selenium\okxselenium2testcase' => 'okinfotech/phpunit-selenium/PHPUnit/Extensions/OkxSelenium2TestCase.php',
                'okinfotech\phpunit\selenium\okxselenium2testcase_driver' => 'okinfotech/phpunit-selenium/PHPUnit/Extensions/OkxSelenium2TestCase_Driver.php',
                'okinfotech\phpunit\selenium\okxselenium2testcase_session' => 'okinfotech/phpunit-selenium/PHPUnit/Extensions/OkxSelenium2TestCase_Session.php',
                'okinfotech\phpunit\selenium\okxselenium2testcase_sessionstrategy_isolated' => 'okinfotech/phpunit-selenium/PHPUnit/Extensions/OkxSelenium2TestCase_SessionStrategy_Isolated.php',
                'okinfotech\phpunit\selenium\okxselenium2testcase_sessionstrategy_shared' => 'okinfotech/phpunit-selenium/PHPUnit/Extensions/OkxSelenium2TestCase_SessionStrategy_Shared.php',
            ];
            $path = dirname(dirname(dirname(dirname(__FILE__)))) . '/vendor/';
        }

        $cn = strtolower($class);

        if (isset($classes[$cn])) {
            require $path . $classes[$cn];
        }
    }
);

use OKInfoTech\PhpUnit\Selenium\OkxSelenium2TestCase;
OkxSelenium2TestCase::shareSession(false);

bootstrapShared.php:

require_once dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php';

spl_autoload_register(
    function ($class) {
        static $classes = NULL;
        static $path = NULL;

        if ($classes === NULL) {
            $classes = [
                'okinfotech\phpunit\selenium\okxselenium2testcase' => 'okinfotech/phpunit-selenium/PHPUnit/Extensions/OkxSelenium2TestCase.php',
                'okinfotech\phpunit\selenium\okxselenium2testcase_driver' => 'okinfotech/phpunit-selenium/PHPUnit/Extensions/OkxSelenium2TestCase_Driver.php',
                'okinfotech\phpunit\selenium\okxselenium2testcase_session' => 'okinfotech/phpunit-selenium/PHPUnit/Extensions/OkxSelenium2TestCase_Session.php',
                'okinfotech\phpunit\selenium\okxselenium2testcase_sessionstrategy_isolated' => 'okinfotech/phpunit-selenium/PHPUnit/Extensions/OkxSelenium2TestCase_SessionStrategy_Isolated.php',
                'okinfotech\phpunit\selenium\okxselenium2testcase_sessionstrategy_shared' => 'okinfotech/phpunit-selenium/PHPUnit/Extensions/OkxSelenium2TestCase_SessionStrategy_Shared.php',
            ];
            $path = dirname(dirname(dirname(dirname(__FILE__)))) . '/vendor/';
        }

        $cn = strtolower($class);

        if (isset($classes[$cn])) {
            require $path . $classes[$cn];
        }
    }
);

use OKInfoTech\PhpUnit\Selenium\OkxSelenium2TestCase;
OkxSelenium2TestCase::shareSession(true);

Selenium02Test:

class Selenium02Test extends OkxSelenium2TestCase
{
    public static function setUpBeforeClass()
    {
    }

    public static function tearDownAfterClass()
    {
    }

    public function setUp()
    {
        $this->setHost('...');
        $this->setPort(4444);
        $this->setBrowser('chrome');
        //$this->setBrowser('firefox');
        $this->setBrowserUrl('...');
    }

    public function tearDown()
    {
    }

    public function testPageExists()
    {
        $this->url('/');
        // test if browser window stays open when test fails
        $this->assertTrue(false);
    }
}


来源:https://stackoverflow.com/questions/5940214/keeping-selenium-browser-open-with-phpunit-selenium

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!