简体   繁体   中英

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?

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).

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. 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). 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) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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