为什么添加“睡眠1"?在后钩中导致此 Rspec/Capybara 测试通过? [英] Why does adding "sleep 1" in an after hook cause this Rspec/Capybara test to pass?

查看:17
本文介绍了为什么添加“睡眠1"?在后钩中导致此 Rspec/Capybara 测试通过?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 rails 4.0.5、rspec 2.14.1、capybara 2.2.1、capybara-webkit 1.1.0 和 database_cleaner 1.2.0.我在以下功能测试中看到了一些奇怪的行为(模拟用户查看帖子评论,将鼠标悬停在图标上以显示菜单,然后单击菜单项删除评论):

I'm using rails 4.0.5, rspec 2.14.1, capybara 2.2.1, capybara-webkit 1.1.0 and database_cleaner 1.2.0. I'm seeing some weird behavior with the following feature test (which simulates a user viewing a comment on a post, hovering over an icon to make a menu appear, and clicking a menu item to delete the comment):

let(:user){create(:user)}
let(:post){create(:post, author: user)}
let!(:comment){create(:comment, post: post, author: user)}

...

it "can delete a comment" do
  assert(page.has_css? "#comment-#{comment.id}")
  find("#comment-#{comment.id}-controls").trigger(:mouseover)
  find("#comment-#{comment.id} .comment-delete a").click
  assert(page.has_no_css? "#comment-#{comment.id}")
end

这个测试大约有 80% 的时间失败,总是因为从数据库中检索了一些记录为 nil——我得到 NoMethodError: undefined method X for nil:NilClass,对于X的各种值.有时nil是被删除的评论,有时是评论所附的帖子,有时是评论/帖子的作者.

This test fails about 80% of the time, always due to some record being retrieved from the database as nil-- I get NoMethodError: undefined method X for nil:NilClass, for various values of X. Sometimes the nil is the comment that's being deleted, sometimes it's the post that the comment's attached to, sometimes it's the author of the comment/post.

如果我在测试的最后加上sleep 1,它就通过了:

If I add sleep 1 to the end of the test, it passes:

it "can delete its own comment" do
  assert(page.has_css? "#comment-#{comment.id}")
  find("#comment-#{comment.id}-controls").trigger(:mouseover)
  find("#comment-#{comment.id} .comment-delete a").click
  assert(page.has_no_css? "#comment-#{comment.id}")
  sleep 1
end

如果我将 sleep 1 放在 after 块中,它也会通过.

It also passes if I put sleep 1 in an after block.

知道为什么我会收到这些 NoMethodErrors,和/或如果我在所有工作完成后让它休眠一秒钟,为什么测试通过?

Any idea why I get these NoMethodErrors, and/or why the test passes if I make it sleep for a second after all the work is done?

推荐答案

我怀疑您的应用程序中的评论可能会在从数据库中删除之前从页面中消失(这是您断言的最后一件事).这意味着测试可以在删除发生之前进行清理.如果是这种情况,您可以通过等待在测试结束时发生实际删除来修复它.我有这个方法(重新实现 一种方法从 Capybara 2 中删除,但有时仍然需要)

I suspect that it's possible in your application for the comment to disappear from the page (which is the last thing you're asserting) before it's deleted from the database. That means that the test can clean up before the deletion happens. If this is the case you can fix it by waiting for the actual deletion to happen at the end of the test. I have this method around (a reimplementation of a method that was removed from Capybara 2 but is still sometimes necessary)

def wait_until(delay = 1)
  seconds_waited = 0
  while ! yield && seconds_waited < Capybara.default_wait_time
    sleep delay
    seconds_waited += 1
  end
  raise "Waited for #{Capybara.default_wait_time} seconds but condition did not become true" unless yield
end

这样我就可以了

wait_until { Comment.count == 0 }

在测试中.

另一种方法是添加 Rack 中间件来阻止测试结束后发出的请求.此处详细描述了这种方法:http://www.salsify.com/blog/tearing-capybara-ajax-tests 我看到它在解决数据泄漏方面做得非常好,在一套大型 RSpec 功能规范中.

Another approach is to add Rack middleware that blocks requests made after the test ends. This approach is described in detail here: http://www.salsify.com/blog/tearing-capybara-ajax-tests I saw it do a very good job of addressing data leakage in a good-sized suite of RSpec feature specs.

这篇关于为什么添加“睡眠1"?在后钩中导致此 Rspec/Capybara 测试通过?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆