当测试失败时,运行selenium测试的浏览器将关闭。这在尝试调试时无益。我知道我可以选择在失败时进行屏幕截图,但如果没有完整的上下文,这将无济于事。浏览器仍然可用,我可以回击并检查发生了什么。
即使断言失败或找不到元素,有没有办法让浏览器保持打开状态?
答案 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);
}
}