Rspec with Rails 7 and System Tests

Hello world! It’s time for my first post in over 4 years.

I recently set up a new Rails 7 project with Rspec and looked online for tips, as one does. I’ve set up many Rails projects before, but not yet with Rails 7, and it’s been a while. The top result in Google for “rails 7 with rspec” is currently Adrian Valenzuela’s Setup RSpec on a fresh Rails 7 project. His post was really helpful for me shaking off the rust. So rather than writing another post that’s 80% the same, I’ll just share a few additional tips. Think of this post as a companion piece to Valenzuela’s.

Running rails.new

Since you’re using Rspec you can add --skip-test since we don’t need the default MiniTest setup:

rails new your-project -d postgresql --skip-test

Note there is also an option for --skip-system-test but after doing some side-by-side comparisons, I found that if you run --skip-test you are also effectively running --skip-system-test. So if you want system test support – and you probably do – there’s some extra setup you have to do yourself. More on that below.

FactoryBot

Valenzuela notes in a comment on his post that his instructions for adding a spec/factories.rb file are incorrect. But the instructions are still there in the post, so look out for that. You will instead want one file per model in the spec/factories directory (and when you use a scaffold generator it will put factory files there).

System Specs

The configuration shown in his post for spec/support/chrome.rb results in running a headless browser for every system spec, which may be fine for a Javascript heavy site, but could be inefficient for other sites. As explained by Harrison Broadbent in Refactoring from feature specs to system specs:

If we didn’t add this config [see below], RSpec would use selenium for everything. There’s nothing wrong with this… it would just be an unnecessary performance slowdown… rack_test runs a lot faster than selenium, but it doesn’t support javascript. By using rack_test as the default driver for our system specs, they run much quicker. Then we tell RSpec to use selenium for tests that require javascript, since selenium emulates a full browser, and we get the best of both worlds — performance by default, and javascript testing when we need it.

So I’ll recommend using the configuration shown in Broadbent’s post:

#spec/rails_helper.rb

RSpec.configure do |config|
  ...
  config.before(:each, type: :system) do
    driven_by :rack_test # rack_test by default, for performance
  end

  config.before(:each, type: :system, js: true) do
    driven_by :selenium_chrome_headless # selenium when we need javascript
  end
end

If you ran rails.new with --skip-test as I recommended above, you will also need to add the gems shown in Broadbent’s post, since --skip-test also skips the system tests setup (which consists solely of adding these gems):

#Gemfile

group :development, :test do
  ...
  gem "capybara"
  gem "selenium-webdriver"
end

Lastly, I recommend Noel Rappin’s post A Quick Guide to Rails System Tests in RSpec as he has a comprehensive overview and also has tips for updates related to Devise and CircleCI.

Leave a Reply