Speed Up JavaScript Capybara Specs by Blacklisting URLs

On a project recently, our full test suite began to crawl (taking ~9 minutes instead of less than 1) on our local machines running OS X but ran normally on CI. This slowdown took our productivity to near zero. We discovered our Capybara specs with js: true set were the culprit but we couldn’t figure out why.

Finding the Problem

We needed to get more information from the tests so we set the javascript_driver to debug mode. When using Capybara Webkit, that change looked like:

Capybara.javascript_driver = :webkit_debug

After this change, when running the tests, we saw more verbose log output revealing that the tests were running slowly due to loading external Typekits. The specific problem was the following line in our application.html.erb layout:

<script type="text/javascript" src="//use.typekit.net/nco0znv.js"></script>

Fixing the Problem

We didn’t need to load fonts in specs so we made the below change as our first solution to the problem:

<% unless Rails.env.test? %>
  <script type="text/javascript" src="//use.typekit.net/nco0znv.js"></script>
<% end %>

This update did the trick and we were back to sub-1-minute full suite runs. But, editing the layout only for the tests felt dirty.

A Better Way

Capybara Webkit provides a handy way to limit specific external requests. Instead of wrapping the script tag in a conditional we did the following in our spec/rails_helper.rb to block calls to particular URLs:

config.before(:each, js: true) do
  page.driver.browser.url_blacklist = ["http://use.typekit.net"]

With this configuration in place all requests to the listed URLs return a response with an empty body and status of 200. We could then remove the environment check from the layout. Blacklisting the URL at the request level provided the added benefit of a more thorough integration test. The environment check approach could allow for missing methods or typos within the unless block that would not be surfaced until in production.

What’s next

Read the documentation to learn how to get more verbose logs from Capybara.