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" end end
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) html.must_have_css(".comment") end end
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 end
It only took me a few months to figure that out. Thanks to the authors of all those great gems!
Example
I hope this will help you using the amazing MiniTest in your application. My example can be found here.