Running capybara-webkit Specs with Jenkins CI

How to get WebKit-driven integration tests working in a headless Linux environment.

The capybara-webkit gem is a great way to test the JavaScript aspects of a Rails application. I wanted to take my tests to the next level by automating them with the Jenkins continuous integration server, but getting WebKit to run in a headless Linux environment was a bit tricky. Here’s how I did it.

My setup

I have Jenkins deployed with the following stack:

  • Ubuntu 14.04 LTS provided by Linode ($10 USD/month)
  • Nginx configured for HTTPS, acting as a reverse proxy for Jenkins
  • Jenkins installed via the apt package manager
  • Various Jenkins plugins, including the Bitbucket OAuth plugin for restricting access
  • Rbenv for installing and managing Ruby environments needed by my various Jenkins jobs

1. Install Qt libraries

As you may have already encountered on your development machine, the capybara-webkit gem won’t even install unless you have the necessary Qt libraries.

$ gem install capybara-webkit
Fetching: capybara-webkit-1.0.0.gem (100%)
Building native extensions.  This could take a while...
ERROR:  Error installing capybara-webkit:
  ERROR: Failed to build gem native extension.

    /home/deployer/.rbenv/versions/2.0.0-p247/bin/ruby extconf.rb
Command 'qmake -spec linux-g++' not available

Installing these libraries involves a different set of commands for each operating system, and is documented on the capybara-webkit GitHub wiki. For my Ubuntu 14.04 LTS setup, here’s what I had to do:

# as root
aptitude -y install libqt4-dev libqtwebkit-dev

2. Install xvfb and use it to invoke rspec

The tricker problem is that WebKit requires a display.

bundle exec rake spec
...
webkit_server: cannot connect to X server

This isn’t an issue when running tests on my Mac, but on a headless Linux continuous integration server, a workaround is needed.

This workaround is a utility called Xvfb (“X virtual frame buffer”).

# as root
aptitude -y install xvfb

To use it, I had to change how I invoke specs/tests by wrapping the rake command with xvfb-run. Here’s an example:

if type xvfb-run; then
  DISPLAY=localhost:1.0 xvfb-run bundle exec rake test
else
  bundle exec rake test
fi

Now my capybara-webkit tests run great on my CI server.

More best practices for Rails and Jenkins

If you’re setting up Jenkins for the first time, or looking for ways to improve your existing Rails CI approach, check out these additional resources:

  • jenkins-ci.sh is the bash script that Jenkins invokes to test each of my Rails projects. It ensures the required Ruby is installed, creates and migrates the database as necessary, runs Minitest via xvfb, and generates a Brakeman security vulnerability report, among other things.
  • vagrant-jenkins is a recipe I used as a reference for provisioning a DigitalOcean VPS and fully installing and configuring a Jenkins CI server with Rbenv, PostgreSQL, Nginx, and all the techniques described in this post. Fork the project and give it a shot!

Share this? Copy link

Feedback? Email me!

Hi! 👋 I’m Matt Brictson, a software engineer in San Francisco. This site is my excuse to practice UI design, fuss over CSS, and share my interest in open source. I blog about Rails, design patterns, and other development topics.

Recent articles

RSS
View all posts →

Open source projects

mattbrictson/nextgen

Generate your next Rails app interactively!

11
Updated 1 day ago

mattbrictson/tomo

A friendly CLI for deploying Rails apps ✨

360
Updated 1 day ago

More on GitHub →