使用phpunit / selenium保持selenium浏览器打开

时间:2011-05-09 17:12:51

标签: selenium phpunit

当测试失败时,运行selenium测试的浏览器将关闭。这在尝试调试时无益。我知道我可以选择在失败时进行屏幕截图,但如果没有完整的上下文,这将无济于事。浏览器仍然可用,我可以回击并检查发生了什么。

即使断言失败或找不到元素,有没有办法让浏览器保持打开状态?

6 个答案:

答案 0 :(得分:10)

几周后随机想出来。

启动服务器时,最后使用-browserSessionReuse选项。这将使整个测试期间一个浏览器会话保持打开状态,而不是在失败时关闭

答案 1 :(得分:1)

您可能在测试结束时调用selenium.stop()。您需要注释掉该行代码并确保在测试结束时不会销毁您的selenium对象。这将使窗户保持打开状态。同样的问题已经回答here

答案 2 :(得分:1)

关于https://stackoverflow.com/a/6904808/654026处关于-browserSessionReuse的答案,请记住,您必须处理在测试执行之间清理cookie。否则,您可能难以调试错误。

答案 3 :(得分:1)

一个简单的解决方案是在测试setUp()方法中将session $ stopped属性设置为true。由于该属性是私有的,我们需要使用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 );

        ...
}

答案 4 :(得分:0)

经过长时间的尝试创建一个相对干净的解决方法,我现在采取了非常肮脏,但非常容易的黑客攻击。 phpunit \ selenium源代码不容易覆盖,如果有用于创建Session对象的工厂,那将是很好的。我试图通过覆盖和代理对象来破解对象创建,但仍然无法使其工作。最后,我并不想花更多时间在这上面,而是走最简单,最肮脏的路径,即直接攻击PHPUnit_Extensions_Selenium2TestCase_Session和PHPUnit_Extensions_Selenium2TestCase类的代码。 在PHPUnit_Extensions_Selenium2TestCase中插入了一个静态$ _instance,可用于检查是否存在测试失败情况。在PHPUnit_Extensions_Selenium2TestCase_Session中拦截了stop()方法并查询了TestCase的状态。像魅力一样,但脏脏脏。

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;
}

答案 5 :(得分:0)

这是一个更清洁的解决方案。覆盖了与会话创建相关的所有类。会话类是会话关闭的地方,因此需要覆盖stop()方法。

TODO:添加参数来控制行为,是否以及何时打开浏览器窗口。

重写了5个类:PHPUnit_Extensions_Selenium2TestCase,PHPUnit_Extensions_Selenium2TestCase_Driver,PHPUnit_Extensions_Selenium2TestCase_Session,PHPUnit_Extensions_Selenium2TestCase_SessionStrategy_Isolated,PHPUnit_Extensions_Selenium2TestCase_SessionStrategy_Shared。 创建了2个引导程序文件,1个用于共享浏览器会话,1个用于隔离的浏览器会话。 显示1个示例测试。

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