近况
在我们的Rspec + Capybara + selenium (FF)测试套件中,我们得到了许多不一致的"Capybara::ElementNotFound"错误。
问题是它们只是偶尔发生。通常它们不会在本地发生,它们会发生在CircleCi上,我希望那里的机器更强大(所以更快)?
同样的错误通常不会在单独运行规范时发生,例如运行带有特定行号的rspec:42。
但是请记住,没有一致性。规范不会总是失败。
我们当前的解决方法-睡眠
目前我们唯一能做的就是用'睡眠'乱扔规格。每当我们遇到这样的错误时,我们就把它们加起来,它就会修复它。有时我们不得不增加睡眠时间,这使得测试非常慢,你可以想象。
水豚的默认等待时间是多少?
似乎没有启动,我想测试通常在分配的等待时间(目前为5秒)下失败
一些失败的例子
下面是一个常见的错误:
visit "/#/things/#{@thing.id}"
find(".expand-thing").click
这通常会导致:
Unable to find css ".expand-thing"
现在,在这两行之间放一个sleep来修复它。但是睡觉太残忍了。我可能会加一秒,但代码可能只需要半秒。
理想情况下,我希望水豚的等待时间开始,因为这样它只等待它需要的时间,而不是更长。
<标题>我知道capybara只能做等待的事情,如果选择器还不存在的页面上。但是在上面的例子中,你会注意到我正在访问页面和选择,所以元素还没有在页面上,所以Capybara应该等待。
怎么回事?
标题>我明白了。因此,当您在页面上查找元素时,您可以使用以下几种方法:
first('.some-selector')
all('.some-selector') #returns an array of course
find('.some-selector')
.first
和.all
非常有用,因为它们可以让您从非唯一元素中进行选择。
然而,.first
和.all
似乎不会自动等待元素出现在页面上。
修复
解决方法是始终使用.find()
。.find
将尊重水豚的等待时间。使用.find
几乎完全修复了我的测试(除了一些不相关的异常)。
gotcha当然是你必须使用更多的唯一选择器作为.find
必须只返回一个元素,否则你会得到臭名昭著的Capybara::Ambiguous
异常。
Ember异步工作。这就是Ember通常推荐使用Qunit的原因。他们在代码中绑定了允许在等待异步函数返回时暂停/恢复测试的代码。最好的办法是尝试复制为qunit构建的暂停/恢复逻辑,或者切换到qunit。
在测试过程中有一个全局承诺,你可以连接到:Ember.Test.lastPromise
Ember.Test.lastPromise.then(function(){
//continue
});
另外,访问/点击返回承诺,你需要以某种方式告诉capybara在调用之前暂停测试,然后在承诺恢复后继续。
visit('foo').then(function(){
click('.expand-thing').then(function(){
assert('foobar');
})
})
现在我已经完成了演讲,我意识到从技术上讲,您不是在浏览器内部运行这些测试,而是让它们通过selenium运行,这意味着从技术上讲,它不是在浏览器中运行的(除非selenium在我上次使用它之后做了一些更改,这是可能的)。无论哪种方式,您都需要关注最后一个承诺,并在继续之前等待它,在异步操作之后进行测试。