使用Rspec + Capybara + Ember获得不一致的“无法找到css”错误

时间:2014-05-29 17:01:17

标签: ruby-on-rails selenium ember.js rspec capybara

发生了什么

在我们的Rspec + Capybara + selenium(FF)测试套件中,我们得到了很多不一致的" Capybara :: ElementNotFound"错误。

问题是它们有时只会发生。通常他们不会在本地发生,他们会在CircleCi上发生,我希望机器更强大(并且更快)?

当规范单独运行时,通常也不会发生相同的错误,例如通过运行具有特定行号的rspec:42。

但是请记住,没有一致性。规范不会一直失败。

我们当前的解决方法 - 睡眠

目前,我们唯一可以做的就是通过“睡眠”来破坏规格。每当我们收到这样的错误时我们就会添加它们并修复它。有时我们必须增加睡眠时间,这使得测试变得非常慢,你可以想象。

水豚的默认等待时间怎么样?

似乎并没有开始我想象,因为测试通常会在分配的等待时间(目前为5秒)内失败

失败的一些例子。

这是一个常见的失败:

visit "/#/things/#{@thing.id}"
find(".expand-thing").click

这通常会导致:

Unable to find css ".expand-thing"

现在,在这两行之间进行一次睡眠可以解决问题。但是睡觉太暴力了。我可能会花一秒钟,但代码可能只需要半秒钟。

理想情况下,我喜欢Capybara的等待时间,因为它只会在需要时等待,而不再等待。

最后的注释

我知道如果选择器还没有在页面上存在,那么水豚只能做等待。但是在上面的示例中,您会注意到我正在访问该页面并进行选择,因此该元素尚未在页面上,因此Capybara应该等待。

发生了什么?

2 个答案:

答案 0 :(得分:1)

想出来了。因此,当您在页面上查找元素时,您可以使用以下几种方法:

first('.some-selector')
all('.some-selector') #returns an array of course
find('.some-selector')

.first.all非常有用,因为它们允许您从非唯一元素中进行选择。

然而.first.all似乎不会自动等待该元素出现在页面上。

修复

然后修复是始终使用.find().find将尊重水豚的等待时间。使用.find几乎完全修复了我的测试(有一些不相关的例外)。

陷阱当然是你必须使用更多独特的选择器,因为.find必须只返回一个元素,否则你会得到臭名昭着的Capybara::Ambiguous异常。

答案 1 :(得分:0)

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已经制造)自从上次使用它以来发生了一些变化,可能)。无论哪种方式,您都需要观察最后的承诺,并等待它继续,然后在异步操作后进行测试。