MiniTest::Spec, Capybara, Rails Integration Tests, and Cells: It Works!

I had a hard time getting MiniTest::Spec working with Capybara matchers, in combination with Rails integration tests and cells tests. I almost switched to Rspec but then finally figured out how simple it is.

Why People Use Rspec.

The reason people use Rspec is: It works. Everything popular is supported out-of-the-box provided by the hard work of the Rspec team. You don’t have to think about how integration tests may work or where that matcher comes from.

In Minitest, which is my personal favourite test gem, you have the following gems to pick from.

  • minitest-spec-rails
  • minitest-rails-capybara
  • minitest-rails
  • minitest-capybara
  • capybara_minitest_spec

There are probably more. I tried combining them but either integration tests didn’t work, matcher here didn’t work, matchers there didn’t work, the page object wasn’t available, and so on. It was a nightmare.

How it works!

Fortunately, the solution was pretty simple.

gem "minitest-rails-capybara"

The awesome minitest-rails-capybara will also install minitest-rails and minitest-capybara.

In your test_helper.rb, you add the following line.

require "minitest/rails/capybara"

Which loads all necessary files and add capybara spec matchers to the test base classes.

Integration Tests

Integration tests then I do as follows.

class CommentIntegrationTest < Capybara::Rails::TestCase
  it do
    visit "/comments"
    page.must_have_content "h1"

It’s important to derive your test from Capybara::Rails::TestCase which is totally fine for me as I don’t like describe blocks that magically create a test class for you. Separate test classes just make me feel safer.

No Controller Tests.

I don’t write controller tests in Rails anymore because they are bullshit. They create the illusion of a well-tested system. In production, it will break. This is a result of this code.

Right, that’s 700 lines to setup a fake environment for your tested controller. 700 lines of code are 100% likely to diverge from real application state: Your tests will pass, your code in production breaks.

In the Trailblazer architecture, controller tests are taboo, you only write real integration tests, operation tests, and cell tests, which brings me to the next point.

Cell Tests

The only problem I had with this approach was that my cell tests broke.

class CommentCellTest < Cell::TestCase
  controller ThingsController

  it do
    html = concept("comment/cell/grid", thing).(:show)

I got exceptions like the following.

NoMethodError: undefined method `assert_content' for 

The solution was to include the new set of assertions into the cell tests, too. I did that in my test_helper.rb file.

Cell::TestCase.class_eval do
  include Capybara::DSL
  include Capybara::Assertions

It only took me a few months to figure that out. Thanks to the authors of all those great gems!


I hope this will help you using the amazing MiniTest in your application. My example can be found here.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s