Dean Marano
Jul 7, 2016 · 4 min read

Here at eSpark Learning, we use Jekyll to host our marketing site, At eSpark Engineering, we love automated testing — most of our codebases require a passing test suite for all changes. As we add more javascript to our Jekyll site, we wanted to add a test framework that would give us real world tests — testing that the HTML was valid was no longer enough.

Acceptance Testing with RSpec, Capybara, and Selenium

To create real world acceptance tests for our site, we used a few technologies we were familiar with:

  • RSpec — Behavior Driven Development for Ruby
  • Capybara — Testing of web applications via simulation of a real user’s interaction with your app
  • Selenium — Browser automation

This trifecta sets up a way to write tests (RSpec) and drive the browser (Selenium) using a acceptance test API (Capybara). This gets us most of the way there, but we’re left with one problem — how do we serve the static site, so we can actually test it?

Enter Rack-Jekyll

Most popular Ruby applications (such as Ruby on Rails and Sinatra) use the Rack interface to connect web requests to Ruby code. Since Jekyll generates static pages, it doesn’t have a Rack interface by default — however Rack-Jekyll is a gem that bridges the gap, and allows us to serve our pages to Selenium so we can test it using the browser.

Testing Jekyll, From Scratch

Starting from a Jekyll site, we’ll walk through the steps in getting setup with your first test. For the purposes of this example, we’ll start with a clean Jekyll site.

jekyll new tested-jekyll
cd tested-jekyll

Setting Up Your Gemfile

If you don’t already have one, we’re going to create a Gemfile so we can include additional gems.


source ''gem "jekyll"group :development, :test do
gem "rspec"
gem "selenium-webdriver"
gem "chromedriver-helper"
gem "capybara"
gem "rack-jekyll"
gem "pry"

Note: Pry is a debugger that we use for debugging Ruby, and chromedriver-helper allows us to use the Google Chrome browser instead of the default Firefox browser.

After you’ve created this, run bundle install to install the gems.

Setting Up RSpec

Next, we’ll generate the necessary configuration files for RSpec using rspec — init.

$ rspec --init
create .rspec
create spec/spec_helper.rb

This creates two files — .rspec is a configuration file for RSpec output, and spec/spec_helper.rb is the file that loads your tests and configures the environment. To setup RSpec to use Capybara and Rack-Jekyll, we’ll need to modify this file as noted:


# Require all of the necessary gems
require 'rspec'
require 'capybara/rspec'
require 'rack/jekyll'
require 'rack/test'
require 'pry'
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
# Configure Capybara to use Selenium.
Capybara.register_driver :selenium do |app|
# Configure selenium to use Chrome., :browser => :chrome)
# Configure Capybara to load the website through rack-jekyll.
# (force_build: true) builds the site before the tests are run,
# so our tests are always running against the latest version
# of our jekyll site. = true)

Note: For brevity, all generated comments have been removed

Writing Your First Test

Create a file in the spec/ directory called sample_spec.rb. The *_spec.rb suffix is needed for all files you want RSpec to run automatically.


describe "sample", type: :feature, js: true do
it "has the page title" do
visit '/'
# `binding.pry` is useful for crafting the right selector
# or checking the actual state of the page
binding.pry # test will pause here
expect(find('.post-link').text).to eq('Welcome to Jekyll!')

Then run bundle exec rspec. This will

  • Build your Jekyll site
  • Open a Chrome browser
  • Run your tests
  • Pause after the page loads.
$ bundle exec rspec
Configuration file: /Users/dean/github/espark/tested-jekyll/_config.yml
Generating site: /Users/dean/github/espark/tested-jekyll -> /Users/dean/github/espark/tested-jekyll/_site
From: /Users/dean/github/espark/tested-jekyll/spec/sample_spec.rb @ line 4 : 1: describe "sample", type: :feature, js: true do
2: it "has the page title" do
3: visit '/'
=> 4: binding.pry
5: expect(find('.post-link').text).to eq('Welcome to Jekyll!')
6: end
7: end
[1] pry(#<RSpec::ExampleGroups::Sample>)> exit
Finished in 4.16 seconds (files took 0.88228 seconds to load)
1 example, 0 failures

I’ve left a binding.pry debugger point, which will allow you to interact with the page using Capybara’s find, find_all, click, etc. For more documentation on how to use Capybara to interact with your page, check out the Domain Specific Language (DSL) documentation.

To exit pry, you can use ctrl-d or type exit. The test should run, and complete successfully. You can remove the binding.pry to have the tests run without user interaction.


If all went well, you should have a complete acceptance testing framework for your Jekyll site. From here, it’s easy to set up with your Continuous Integration testing platform (we use CircleCI) to run tests on every branch before merging.

We’ve been using this to ensure our autocomplete forms work as expected, our modals don’t break as we refactor code, and that our new features work as expected. You can find an example repo on Github at espark/tested-jekyll. Happy testing!

eSpark Engineering Blog

A collection of writings from our team on challenges, successes, and other (sometimes) insightful things

Dean Marano

Written by

Runner. Cyclist. Musician. Javascript, Ruby, Clojure Developer. Grad Student. Divvy enthusiast. Feminist.

eSpark Engineering Blog

A collection of writings from our team on challenges, successes, and other (sometimes) insightful things

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade