Rails System Test with Sam Phippen
If your answer to all three of these questions is “yes”, this episode is for you. Because there’s a new way to write these kinds of full-stack acceptance tests in RSpec, and guest chef Sam Phippen is going to show you how to do it. Enjoy!
Video transcript & code
Since RSpec version 3.7 and Rails 5.1, there is a new sanctioned way of doing this called "system test".
Let's start by newing up a
rails new my_app and adding an RSpec install gem "rspec-rails", "~> 3.7" bundle install bundle exec rails g rspec:install
Now, writing a system test can be done by adding the system type to a spec file:
require 'rails_helper' RSpec.describe "the home page", type: :system do it "works" do visit "/" end end
bundle exec rspec. You'll notice that a Chrome window pops
up in the background. This test fails, because we haven't
added anything to the root of our website yet.
By default, system tests use Chrome to test your application. They do this because Chrome is a real browser, and so is likely to give you the most accurate feedback on what your users are experiencing.
Let's unpack what's going on in our test a little bit. System tests include all the default Capybara methods. These are the methods that you're used to calling in your feature tests. Let's generate a controller
bundle exec rails g controller home index
and mount it on the root of our site
Rails.application.routes.draw do get 'home/index' root to: "home#index" end
Now, let's modify our test to make an assertion about the page. We'll match against the default page title generated by Rails.
Running our test this time, we can see that it's passed .
require 'rails_helper' RSpec.describe "the home page", type: :system do it "works" do expect(page).to have_content("index") end end
We were able to find a page and assert something about it's content!
One thing that's really neat about system tests is that it takes a screenshot when your test fails, and if you're using certain terminals (including iTerm2) it'll print the screenshot on the terminal when the test fails. RSpec also prints the location of the screenshot when the test fails. Let's break our test ,
require 'rails_helper' RSpec.describe "the home page", type: :system do it "works" do expect(page).to have_content("monkey") end end
and run it again . You'll notice here in the terminal that we've got a picture, showing us what the page looked like when our test failed.
Have you ever been confused by a failing test, only to finally realize that the element you're looking for isn't showing at all? Screenshots are a great help to debugging in these situations.
require 'rails_helper' RSpec.describe "the home page", type: :system do before do driven_by(:rack_test) end it "works" do visit "/" end end
You may be wondering: how does this differ from classic RSpec feature tests? Well, the implementation of feature tests involve a lot of complexity that was invented by RSpec maintainers and was not supported by any official Rails APIs. System tests on the other hand rely on clean APIs exposed by Rails and maintained by the Rails team.
And that's it for today. Happy hacking!