June 23, 2015

Better content assertion for MiniTest and Capybara

I like to play with MiniTest. It is the opposite of RSspec. Almost no DSL and a lot of pure Ruby code. You can use minitest/spec to imitate RSpec syntax, but I don't like it.

But there is one drawback. If I want to make a content assertion with Capybara, but without minitest/spec, then I have to do something like this:

assert page.has_content?('Hello world')

The issue is that this assertion is reticent:

  1) Failure:
EventsTest#test_event_search [integration_test.rb:17]:
Failed assertion, no message given.

Please note this part: Failed assertion, no message given.

It is not very useful, because I have to check the line number of failed assertion and relevant line in the test file to see what content is missing. It is tedious.

Because of this I've defined my own assertion (and refutation), which is more eloquent:

# test/test_helper.rb
class ActionDispatch::IntegrationTest
  def assert_content(content)
    assert page.has_content?(content), %Q{Expected to found "#{content}" in: "#{page.text}"}
  end

  def refute_content(content)
    refute page.has_content?(content), %Q{Expected not to found "#{content}" in: "#{page.text}"}
  end
end

And the failure now looks like this:

  1) Failure:
EventsTest#test_event_search [integration_test.rb:17]:
Expected to found "Hello world" in: "This is the text from the tested web page"

Now I can immediately see what content is missing. I don't have to lookup it in the test and I can immediately work on the fix, which results in much better programming flow.

Hey there!

My name is Patrik Bóna and I am the only programmer at Memberful. This blog is kind of dead, but I just started my own Ruby on Rails screencast. Follow me on Twitter if you want to be notified about my newest videos.