How to avoid sleep in Rails system tests

0
42
How to avoid sleep in Rails system tests


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.

The problem

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:

# ...

sleep 0.5

assert_not page.has_content?("Failure")

Similarly, the same issue is true for other assertions:

assert_not page.has_css?(".flash")

The fix

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_field?, has_no_link?, has_no_table?, and other Capybara negative assertions.

We can also adjust the maximum waiting time with default_max_wait_time:

Capybara.default_max_wait_time = ENV.fetch("MAX_WAIT_TIME_IN_SECONDS", 5).to_i

Finally, we might find ourselves in a situation we still need to use sleep. In that case, we can write a helper that can sleep up to our predefined wait time:

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  ...

  def wait_until
    Timeout.timeout(Capybara.default_max_wait_time) do
      until value = yield
        sleep(0.1)
      end
      value
    end
  end

# in test

  wait_until do
    page.page_path == current_path
  end

Conclusion

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 sleep calls.

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

More →



Source link

Leave a reply

Please enter your comment!
Please enter your name here