Writing system tests can be sometimes tricky because we want to assert a reality that’s not yet rendered. Ad-hoc sleeping is something that can mostly address the problem, but it’s not the most elegant solution and should be avoided if possible.
When we write a test with Capybara, we might request an action that takes a bit longer to manifest.
Imagine a form submit that updates a record:
page.fill_in :data, with: "foo bar" page.click_on "Update" # test the expectation assert page.has_content?("Success")
In this case, Capybara has us covered.
has_content? will wait.
What about if we want to assert the opposite?
# ... assert_not page.has_content?("Failure")
This code won’t work as expected, unfortunately. A natural quick fix could be using
# ... sleep 0.5 assert_not page.has_content?("Failure")
Similarly, the same issue is true for other assertions:
Fix is mostly easy. It’s important to use the Capybara alternatives for asserting the negative:
# will wait assert page.has_no_content?("Success") # will wait assert page.has_no_css?(".flash")
In a similar fashion, we should rely on
has_no_table?, and other Capybara negative assertions.
We can also adjust the maximum waiting time with
Capybara.default_max_wait_time = ENV.fetch("MAX_WAIT_TIME_IN_SECONDS", 2).to_i
If we need to increase this number just for one test, there is
using_wait_time that takes the number of seconds:
# in test using_wait_time(5) do assert page.has_no_css?(".flash") end
If we need to use
sleep with something else than Capybara helpers, we can write a helper sleeping up to a predefined wait time:
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase ... def wait_until(time: Capybara.default_max_wait_time) Timeout.timeout(time) do until value = yield sleep(0.1) end value end end # in test wait_until(time: 2.5) do page.page_path == current_path end
We cannot really avoid sleeping in Rails system tests, but we should let Capybara do the heavy lifting and skip polluting our tests with random
sleep calls. Also,
sleep is a tool. If you open a Capybara test suite, you’ll find ad-hoc
← IT'S OUT NOW
I wrote a complete guide on web application deployment. Ruby with Puma, Python with Gunicorn, NGINX, PostgreSQL, Redis, networking, processes, systemd, backups, and all your usual suspects.