Rails Feature Tests With RSpec and Capybara-Webkit

Posted January 26, 2017 by Robert Cox in Development, Testing

Using RSpec and Capybara-Webkit provide a great workflow for writing feature tests for your rails application. This allows you to write automated tests that are simulating page visits, clicks, filling out forms, etc. This can be extremely valuable in that it is checking every layer of code behind the processes that you instruct it to perform.

Have more confidence in your code

Testing code is an integral step in the workflow developing applications. It allows the developer to have a certain level of comfort while working, that the tested code won't be broken by implementing new code.

It can be stressful trying out new techniques and technologies in an existing code base, so having a test suite ensuring that the rest of the code isn't being broken has immediate benefits.

The tools I use for feature testing are RSpec, and Capybara-Webkit.

RSpec is a DSL (Domain Specific Language) written in and for Ruby. It is a vastly popular language used for test Ruby code, even though Ruby comes with test::unit built in.

Capybara is an acceptance testing framework, which tests the application as if from a user's perspective.

The purpose of this post is to give you a basic understanding of how to implement Capybara

Writing the feature test

Before you get started writing the code, I need to make sure that you have everything necessary installed.

One common cause of failure when installing Capybara-Webkit on Mac OS X is the lack of QT. Since I am using Homebrew, instillation is as simple as entering brew install qt into the command line, and hitting return .

With that done, I head over into my project's Gemfile and add the following:

group :test, :development do
  gem 'rspec-rails'
end

group :test do gem 'capybara-webkit' end

Ensure that the Bundler gem is installed gem install bundler, then simply run bundle install, and that should install RSpec and Capybara-Webkit.

Head over to the spec_helper.rb file, and add the following line

require 'capybara/rspec'

Here I am going to be testing the completion of a login form. I am using Devise for user authentication.

Inside of the spec/features/users/login_spec.rb file, ensure that you include require "rails_helper".

Since this form is assuming that there is already an existing user that is signing in, a user needs to be created for it to login with.

feature "User sign in" do
  scenario "existing user signs in" do
    user = User.create(email: "user@test.com", password: "helloworld")
  end
end

Now that it has the user, I am going to want to instruct Capybara to visit the user login page, in this case this is accomplished using the new_user_session_path . We now have:

feature "User sign in" do
  scenario "existing user signs in" do
    user = User.create(email: "user@test.com", password: "helloworld")
    visit new_user_session_path
  end
end

One great thing about Capybara, is its ability to interact with the website as if it were a user. You are able to use commands such as visit, click_link, click_button, fill_in, and more. A list of commands can be found on this capybara cheat sheet.

We are going to want to have our test fill_in the Email text box with the email address we created. This will be done by entering

fill_in "Email", with: "user@test.com"

We then do the same for the Password field.

fill_in "Password", with: "helloworld"

Clicking the sign in button is as easy as click_button "Sign in", this is why I love Capybara!

The only thing left for our test to do is to expect that something happens! In this case, we are going to expect that our message stating "Signed in successfully" is shown after a successful sign in. This leaves us with:

feature "User sign in" do
  scenario "existing user signs in" do
    user = User.create(email: "user@test.com", password: "helloworld")
    visit new_user_session_path
    fill_in "Email", with: "user@test.com"
    fill_in "Password", with: "helloworld"
    click_button "Sign in"
    expect(page).to have_text "Signed in successfully."
  end
end

Now that the test is written, we head back to the command line, ensuring that we are in our project's directory.

Since I stored this test inside of the spec/features/users/signin_spec.rb file, I am going to run rspec spec/features/users/signin_spec.rb.

After receiving the message 1 example, 0 failures, I can walk away knowing that this form works. Now if a feature is implemented that breaks it, we will know because this test will fail.

Feature tests are meant to test the high-level processes by interacting with the application as if by a user. Unit testing will go much more in depth, and allow you to test the individual methods being run behind the scenes.

Vaporware

Related Insights