Testing Your App In The Browser With Capybara (Rails Backend, React Frontend)

Ethan Ryan
5 min readDec 7, 2017

--

capybara chillin with some monkeys

In my last blog post, I wrote about testing Rails apps with Minitest and RSpec.

In this blog post, I’ll talk about getting started with testing Rails apps using Capybara.

0. What Is It?

According to the documentation, Capybara is an “acceptance test framework for web applications”, named after the largest living rodent in the world.

According to the Daily Mail, the capybara is also the friendliest creature in the world. Everyone’s cool with capybara, even alligators!

capybara chillin with an alligator

1. Setup

Setting up Capybara is easy.

First, add this line to your Gemfile and run bundle install:

gem 'capybara'

Then add this line to your test helper file, AKA spec_helper.rb:

require 'capybara/rails'

2. Start Testing

I’m using RSpec, so I added a folder to spec, spec/features

Within that folder, I created a file, home_spec.rb, that looks like this:

require 'spec_helper'class Home
include Capybara::DSL
def visit_homepage
visit('/')
end
end
feature "Visit homepage" do
let(:home) {Home.new}
scenario "Able to see text, Word Nerds", :js => true do
home.visit_homepage
expect(page).to have_content("Word Nerds")
end
end

I got the above code from this tutorial.

To run that spec (and all my specs) I run the command rspec in Terminal.

This gave me the errors:

1.1) Failure/Error: visit('/')LoadError:Capybara's selenium driver is unable to load `selenium-webdriver`, please install the gem and add `gem 'selenium-webdriver'` to your Gemfile if you are using bundler.1.2) Failure/Error: raise LoadError, "Capybara's selenium driver is unable to load `selenium-webdriver`, please install the gem and add `gem 'selenium-webdriver'` to your Gemfile if you are using bundler."

To fix those, I followed the error’s instructions and added gem 'selenium-webdriver' and ran bundle.

This lead to some more errors:

Selenium::WebDriver::Error::WebDriverError:Unable to find Mozilla geckodriver.

Which lead to some googling, which lead to running gem install webdrivers

[intermission]

…update after lots of changes…

Forget what I said earlier about setting up Capybara being easy. For me, it took a bit of trial and error, reading through the docs, and lots of other people’s tutorials, till I got it working.

Note my app has a Rails backend and a React frontend.

This tutorial lead me to use Capybara with Poltergeist and PhantomJS, and this Learn.co introduction to Capybara influenced how I wrote my tests. Thanks Flatiron School!

Also, I found this diagram helpful:

testing, testing, one two three

Unit tests test the Models, which interact with the database.

Controller tests test the Controllers, which communicate info between the models and views. A controller accepts input and sends commands.

Integration tests test the Views in the browser as well as the user experience. In other words, what’s being presented as HTML to users of the app.

Setup, v2.0

Here’s how I finally got some simple integration tests passing for my app:

#Gemfile
group :test do
gem 'phantomjs'
gem 'poltergeist'
gem 'capybara'
end

Ran bundle for those gems.

Generated a rails_helper file by running rails generate rspec:install

The rails_helper file requires spec_helper. The rails_helper file is the newer way to run RSpec. That caused some confusion for me, since I was referencing older Stack Overflow answers to some of the issues I was encountering.

Defined poltergeist as my driver:

require 'capybara/poltergeist'Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, {
js_errors: false,
# js_errors: true, #setting this to true outputs all my console.logs to Terminal
phantomjs_options: ['--ignore-ssl-errors=yes', '--ssl-protocol=any'],
debug: false,
timeout: 500,
phantomjs: File.absolute_path(Phantomjs.path)
})
end
Capybara.javascript_driver = :poltergeist
Capybara.default_driver = :poltergeist

Within my spec directory, I created a features folder, and within that I created a file, home_spec.rb, so named to test my app’s homepage.

Testing, v2.0

I had some trouble with the Capybara visit method, because I thought I’d be able to visit('/') to visit my homepage, but that kept giving me errors. That route would probably work if my whole app were a Rails app, but my frontend was build with React. Finally I realized I need to visit the actual URL.

I tested this by first visiting my API:

describe "GET '/users' - from API", :type => :feature do
it 'checks the first user in the database' do
visit('http://localhost:3000/users')
expect(page).to have_content("bob")
puts 'cool, bob is in the house!'
end
end

which passed.

Then I tested it by visiting Google:

describe "GET Google homepage", :type => :feature do
it 'welcomes the user to Google' do
visit('https://www.google.com/')
expect(page.title).to have_content("Google")
puts " cool, Google's title is 'Google' "
end
end

which passed.

Finally, I started testing my app, by visiting it at the URLs where I could expect to find it, since I had my backend and frontend servers running:

describe "GET '/' - homepage title", :type => :feature do
it 'welcomes the user to Word Nerds' do
visit('http://localhost:3002/')
expect(page.title).to have_content("Word Nerds")
puts 'the homepage title is Word Nerds'
end
end
describe "GET '/' - homepage", :type => :feature do
it 'welcomes the user to Word Nerds' do
visit('http://localhost:3002/')
expect(page).to have_content("Word Nerds")
puts 'cool, the homepage has words on it'
end
end
describe "GET '/login", :type => :feature do
it 'shows a login form' do
visit('http://localhost:3002/login')
expect(page).to have_content("Login")
puts 'cool, the login form page says Login'
end
end

Success

Oh, the sweet smell of passing tests in Terminal.

bob is in the house

You can see my integration tests are passing, as well as the unit tests I made in my last blog post.

RSpec runs tests in random order by default, and that’s what was happening with my tests previously. Now they are no longer running in random order for some reason.

One quick fix for this is by running rspec --order rand, which returns:

cool, random

This blog post was intended to be a brief one, simply showing how to get started testing your app in the browser with Capybara. Once you get some simple tests passing, like visiting the homepage, you can then start testing a lot of other behaviors of users interacting with your app, like:

clicking buttons:

click_button 'Like'

and filling out forms:

fill_in 'Name', with: 'Batman'

You can even take screenshots of the page:

page.save_screenshot('screenshot.png')

Capybara is cool!

capybara chillin with some birds

Happy testing.

--

--