Rule of thumbs against flaky specs

Updated . Posted . Visible to the public. Repeats.

Here are a few common patterns that will probably lead to flaky specs. If you notice them in your specs, please make sure that you have not introduced a flaky spec.

Using RSpec matchers

One rule of thumb I try to follow in capybara tests is using capybara matchers and not plain rspec matchers.

One example:

visit(some_page)
text_field = find('.textfield')
expect(text_field['value']).to match /pattern/

This can work, but is too brittle and flaky. match will not retry or synchronize the value of text_field.

The equivalent code with a capybara matcher:

visit(some_page)
expect(page).to have_field('.textfield', with: /pattern/)

have_field will retry for and synchronize the text_field.

Using .limit(N)

If your asserting a list of records that is somehow limited via a .limit clause, make sure your order is deterministic, otherwise you'll receive different records in different runs. For example:

# User(id bigint, ends_on: Date)
User.order(:ends_on).limit(5) # Bad, because the order is not deterministic if a lot of users end on the same date

User.order(:ends_on, :id).limit(5) # Better, because it takes the id into account in such a case

Using an external ui component library

If you're using an external UI component library, you've probably introduced a lot of flakyness to your spec. UI Components often introduce autoplay features, animations, take longer to initialize, are lazy loaded etc. Make sure you have a safe way to assert against the most glaring issues in your component. Often times, there's a good aria-* selector you can assert against. E.g.

expect(page).to have_selector('.modal[aria-hidden="false"]') # wait for the modal
expect(page).to have_css("[data-datepicker-loaded='true']") # make sure the datepicker is loaded before interacting with it
Niklas Hä.
Last edit
Niklas Hä.
License
Source code in this card is licensed under the MIT License.
Posted by Niklas Hä. to makandra dev (2022-09-30 13:22)