简体   繁体   English

使用Capybara / Rspec进行的间歇性功能测试失败:期望{单击}。更改{…}

[英]Intermittent failing feature tests using Capybara/Rspec: expect { click }.to change { … }

We have a few feature specs that occasionally fail that a rerun fixes. 我们有一些功能规格,有时会因重新运行而失败。 I have a lot of experience testing around Capybara timing, but in this particular case I'm not actually sure how to fix it. 我有很多有关水豚计时的测试经验,但是在这种特殊情况下,我实际上不确定如何解决它。 Trying to web search for this has been surprisingly ineffective. 尝试通过网络搜索此方法的效果令人惊讶地无效。

Here's the code we have that fails: 这是我们失败的代码:

expect {
  click_on 'Save'
}.to change { Report.count }.from(1).to(2)

There's a couple of different ways I can think to do this: 我可以通过几种不同的方式来做到这一点:

expect(Report.count).to eq 1
click_on 'Save'
expect(Report.count).to eq 2

Or perhaps: 也许:

expect(Report.count).to eq 1
click_on 'Save'
expect(page).to have_something
expect(Report.count).to eq 2

But given that these tests fail so randomly and infrequently, it's difficult to test that we're doing it right. 但是鉴于这些测试如此随机且很少失败,因此很难测试我们是否做对了。

What is the correct way to verify a count changed based on a click in Capybara? 验证基于水豚点击的count变化的正确方法是什么?

Firstly, direct DB checks in feature/system tests (which I assume is what you're writing since you're using Capybara is generally a bad code smell since you should generally be verifying things through visual changes on the page (they make more sense for request/controller tests). 首先,在功能/系统测试中直接进行数据库检查(我假设这是您正在编写的内容,因为您正在使用Capybara,这通常是一种不好的代码味道,因为您通常应该通过页面上的可视化更改来验证事物(它们更有意义)用于请求/控制器测试)。

If you insist on doing direct DB feature tests you still need to use visual checks to synchronize those checks. 如果您坚持进行直接数据库功能测试,则仍然需要使用视觉检查来同步这些检查。 This is because actions like click_on have no knowledge of any further browser action those clicks initiate and can just return immediately after clicking. 这是因为诸如click_on操作不知道这些单击引发的任何其他浏览器操作,并且可以在单击后立即返回。 Since the count won't actually be changed until after a request is processed you need to delay until that request is completed (usually done by waiting for a visible page change that indicates it has completed). 由于count实际上要等到处理完请求后才会更改,因此您需要延迟直到该请求完成为止(通常是通过等待可见的页面更改来表明请求已完成)。 Therefore the correct way would be 因此正确的方法是

expect(Report.count).to eq 1
click_on 'Save'
expect(page).to have_something # wait for something that indicates the request triggered by click_on has completed
expect(Report.count).to eq 2

which could also be written as 也可以写成

expect {
  click_on 'Save'
  expect(page).to have_something
}.to change { Report.count }.from(1).to(2) 

or more flexibly as 或更灵活地

expect {
  click_on 'Save'
  expect(page).to have_something
}.to change { Report.count }.by(1) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM