We are a software consultancy based in Berlin, Germany. We deliver
high quality web apps in short timespans.

Upstream Agile GmbH Logo

Capybara - Mix and match acceptance testing

April 26, 2010 by thilo

The more layers you add when testing your application the slower these tests become.

A unit test takes a fraction of a second to run. A simple integration test maybe up to a second. When JavaScript and a real browsers gets involved probably longer. But unnecessary long test runs hurt productivity. Up until a couple of weeks ago I had to make trade-offs either in speed, test-coverage or maintainability of my test suite when it came to real full stack integration/acceptance testing. Here is how I perceive these problems.

A standard Cucumber (a framework to write natural readable acceptance tests) setup uses Webrat which interacts with your app through a simple Rails integration session, so no JavaScript. The best what Webrat could do in this scenario, when it comes to JavaScript, is to recognize some common patterns in your html and send according requests - but still, most of the JavaScript code is not covered.

Webrat can also be used to drive Selenium, which interacts with your web app through a real browser. This will cover Javascript, CSS and possible browser issues. But compared to Webrat Selenium is snail mail slow.

With Culerity or Steam there are alternatives to Webrat which use HtmlUnit: HtmlUnit is a “GUI-Less browser for Java programs”. It models HTML documents and provides an API that allows you to load pages, fill out forms, click links, etc… just like you do in your “regular” browser. They are significantly faster than scripting a normal browser with Selenium at the cost that you don’t see how design works or if any browser issues cause trouble and it is still slower than Webrat without a special backend.

In order to run acceptance tests which require full JavaScript support separately from those who don’t to get shorter test runs I use two separate environments as they are generated out of the box either by Cucumber or Culerity. This leads to duplication of the setup code and step definitions, which means that there is more to maintain and more that could possible break.

Capybara addresses the shortcomings of a two environments solution and still allows you to be flexible in what backend you use for integration testing on a per scenario basis in Cucumber. It does that by using Cucumber’s tags feature.

Capybara “is inspired by and aims to replace Webrat as a DSL for interacting with a web application. It is agnostic about the driver running your tests and currently comes bundled with rack-test, Culerity and Selenium support built in”. In the future we certainly will see other backends. I saw that a backend for env-js (a pure JavaScript browser environment) is a already in the making.

Below is an example that runs one scenario with Selenium and the other with Culerity.

  @selenium
  Scenario: Searching a blog post using autocomplete
    Given a blog post titled "Autocomplete made easy" containing "Some example"
    When I go to the search page
      And I fill in "Search" with "Auto"
      And I follow "Autocomplete made easy"
    Then I should see "Some example"

  @culerity
  Scenario: delete found comments
    Given a comment by author "Thilo"
    Given a comment by author "Tilo"
  When I search for "ilo"
    And I check the element with xpath "//p[contains(@class,'delete')]/input"
    And I press "Submit"
  Then I should see "Are you really sure?"
  When I press "Yes"
  Then I should see "Comments were delete"
  And I should see "0 Comments"

You might have noticed the XPath expression in the second scenario. From time to time you will have to deal with XPath expressions when writing custom steps as XPath is used to locate elements within the DOM. The default steps can be scoped with CSS selectors or XPath, Capybara takes care of the conversion to XPath then.

Using Capybara with Cucumber is straightforward: First get the gem:

gem install capybara

On OSX you may have to install libffi, you can install it via MacPorts with:

sudo port install libffi

Then go to your rails project and generate the cucumber files as followed:

script/generate cucumber --capybara

And you are ready to go to mix and match your acceptance with tags. For further informations like using capybara without cucumber, asynchronous JavaScript etc. checkout Capybara’s README.

Capybara definitely eases maintaining acceptance test and will give impulses to improve other tools, e.g. env-js.

Are you stuck in a maintenance nightmare or simply want to bring your testing skills to the next level? Get in touch with us.

Hello Explorer!

You’ve found our very old Website Archive (2007-2012). It’s a bit out of date, but we love looking back at how it all started - and how far we’ve come since then! We’re now fully focused on building our coworking management product, Cobot.

Take a look →