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 thanselenium
, but it doesn’t support javascript. By usingrack_test
as the default driver for our system specs, they run much quicker. Then we tell RSpec to useselenium
for tests that require javascript, sinceselenium
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.