In Progress
Unit 1, Lesson 1
In Progress

Rails System Test with Sam Phippen

Do you write Rails applications? Do you use RSpec to do behavior-driven design on your Rails applications? Do you like to create at least a few full-stack tests to verify that everything from the front-end JavaScript to the database queries is working properly?

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

Today we're talking about testing the full stack of your Rails application, including Javascript, with RSpec.

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 application

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

Let's run 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.

But what if I don't want Javascript? I hear you cry. Well, system tests support that too. There are many browser drivers available to you out of the box, using a method called driven by. If you don't want Javascript, you can use the Rack test driver:

require 'rails_helper'

RSpec.describe "the home page", type: :system do
before do
driven_by(:rack_test)
end

it "works" do
visit "/"
end
end

Running this time , you'll notice no browser pops up. Rack test interfaces with your Rails app by making requests and parsing the HTML that comes back. It doesn't execute Javascript at all. If you want to write an integration test that runs against your app, but doesn't need Javascript, this is how I'd recommend doing it. Rack test runs much faster than booting a real browser, and so you'll get some benefit from running like that.

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.

To conclude: system testing is a really easy way to get access to full stack testing of your Rails applications including Javascript. System tests are the future of full-stack testing in Rails applications, and both the RSpec and Rails teams recommend you use them.

And that's it for today. Happy hacking!

Responses