我在Behat等待元素“滑入”时遇到了麻烦。
在我们的管理面板菜单中,每个主要项目向下滑动以显示子菜单,如下所示:
为了清晰起见,我添加了红线以显示菜单,并为子菜单添加了绿色。
问题是,这个菜单“滑入”。这是一个可爱的效果,但它破坏了我的测试。 :)
我正在尝试使用spin function让Behat等到子菜单可见后再尝试点击它。
代码:
/**
* @When I wait for :cssSelector
* @param $cssSelector
* @throws \Exception
*/
public function iWaitFor($cssSelector)
{
$this->spin(function($context) use ($cssSelector) {
/** @var $context FeatureContext */
return !is_null($context->getSession()->getPage()->find('css', $cssSelector));
});
}
/**
* @When I wait for :text to appear
* @Then I should see :text appear
* @param $text
* @throws \Exception
*/
public function iWaitForTextToAppear($text)
{
$this->spin(function($context) use ($text) {
/** @var $context FeatureContext */
return $context->getSession()->getPage()->hasContent($text);
});
}
/**
* @When I wait for :text to disappear
* @Then I should see :text disappear
* @param $text
* @throws \Exception
*/
public function iWaitForTextToDisappear($text)
{
$this->spin(function($context) use ($text) {
/** @var $context FeatureContext */
return !$context->getSession()->getPage()->hasContent($text);
});
}
/**
* Based on Behat's own example
* @see http://docs.behat.org/en/v2.5/cookbook/using_spin_functions.html#adding-a-timeout
* @param $lambda
* @param int $wait
* @throws \Exception
*/
public function spin($lambda, $wait = 60)
{
$time = time();
$stopTime = $time + $wait;
while (time() < $stopTime)
{
try {
if ($lambda($this)) {
return;
}
} catch (\Exception $e) {
// do nothing
}
usleep(250000);
}
throw new \Exception("Spin function timed out after {$wait} seconds");
}
该功能的片段:
@javascript
Scenario Outline: Create a new piece of artwork
Given I am logged in to the CMS as "adminUser"
Then I should see "Artwork"
When I follow "Artwork"
Then I should see "Pieces" appear
When I follow "Pieces"
Then I should see "Manage Artwork Pieces"
然而,虽然这在我的Vagrant开发环境中运行得非常好,但是当Jenkins在确认已经出现“Pieces”后尝试follow "Pieces"
时,它会中断。两者都在无头linux的XVFB中使用Firefox运行Selenium。
这些是我目前正在使用的版本:
╔═════════════╦══════════════╦════════════╗
║ Environment ║ Development ║ Testing ║
╠═════════════╬══════════════╬════════════╣
║ Linux ║ Ubuntu 14.04 ║ CentOS 6.6 ║
║ PHP ║ 5.5.9 ║ 5.4.38 ║
║ Behat ║ 3.0.x-dev ║ 3.0.x-dev ║
║ Selenium ║ 2.45.0 ║ 2.45.0 ║
║ XVFB ║ 1.15.1 ║ 1.15.0 ║
║ Firefox ║ 36.0.4 ║ 31.5.0 ║
╚═════════════╩══════════════╩════════════╝
我将尝试确保Firefox和Selenium都尽可能最新,以确定是否能解决问题,但这一直是一个持续存在的问题,所以我不相信。
附录
我错过了一个实际错误消息的示例:
When I follow "Carousel" # tests/Behat/Cms/Features/1.1.Carousel.feature:11
Offset within element cannot be scrolled into view: (110, 17): http://www.###.co.uk/admin/fp/carousel
Build info: version: '2.44.0', revision: '76d78cf', time: '2014-10-23 20:02:37'
这是在Then I should see "Carousel" appear
此外,错误几乎是随机发生的。我需要一种简单的方法来确保测试不会继续,直到页面处于允许它继续的状态。我想要避免任何类似“等待”或任何依赖于JavaScript或Selenium的东西(如果我切换到另一个驱动程序)。
更新:将测试机上的Selenium更新为2.45.0,仍然遇到同样的问题。修正了Dev Environment上面的PHP版本,有5.4,实际上是5.5.9。
答案 0 :(得分:3)
我相信我已经解决了这个问题,但我不能完全确定原因,所以如果我错了,请纠正我。
我猜测检查页面内容将始终返回true,无论它是否可见。相反,我转而使用Mink提供的断言,这些断言是为每个驱动程序独立实现的。在这种情况下,我们要求Selenium考虑该元素是否存在。
我最初避免使用断言,因为它们会抛出异常,但是,因为异常是特定且可知的,我们可以利用它来为我们带来优势。
这是新代码。
/**
* @When I wait for :text to appear
* @Then I should see :text appear
* @param $text
* @throws \Exception
*/
public function iWaitForTextToAppear($text)
{
$this->spin(function(FeatureContext $context) use ($text) {
try {
$context->assertPageContainsText($text);
return true;
}
catch(ResponseTextException $e) {
// NOOP
}
return false;
});
}
/**
* @When I wait for :text to disappear
* @Then I should see :text disappear
* @param $text
* @throws \Exception
*/
public function iWaitForTextToDisappear($text)
{
$this->spin(function(FeatureContext $context) use ($text) {
try {
$context->assertPageContainsText($text);
}
catch(ResponseTextException $e) {
return true;
}
return false;
});
}
我自从运行测试套件两次以来,每次检查的变体大约发生了100次,他们都回来了。如果有人想提交更好的答案/解释,我现在暂时保留这个问题。