Drivers: or why Capybara rocks

I’m normally very conservative when it comes to adopting new development tools. I want to Get Stuff Done™, not waste my time playing with the latest shiny new toy.

Nevertheless, when Capybara came out I jumped right on it.

Why? Because the existing state of web acceptance testing tools was severely broken, and needed fixing. In particular, the then-dominant tool for testing JavaScript/AJAX was Selenium, and quite frankly, it sucked. When it worked it was slow, but working was not its default state. It was an incredibly fragile, brittle tool, that would break with even the slightest modifications to the test environment, the configuration of furniture in the room where the developer was sitting, or what he/she had for breakfast.

Capybara came onto the scene with an impressively clean codebase, and it brought with it one revolutionary idea: a totally consistent developer-facing API for writing tests and a dead-simple way of swapping in and out back-ends ("drivers" in Capybara-speak), even on a scenario-by-scenario basis.

That is, you could run most of your acceptance tests with Capybara under the ultra-fast rack-test driver, and only drop down to the Selenium level for specific tests which needed to fully exercise the JavaScript/AJAX layer. Not only this, but if you’re not happy with the brittleness of Selenium, you can switch to an alternative driver without modifying a single line of your tests.

So my first experience with Capybara was dropping Selenium for Culerity. Culerity may have its own problems, but it has been orders of magnitude more robust for me than Selenium ever was. (It may be that Selenium has improved since I last had to use it, but from comments I read on mailing lists I see that it is still bring a lot of pain to quite a few unfortunate people out there.)

JRuby and Bundler

For me the main problem that Culerity has is that it brings in a dependency on JRuby into a project which is otherwise pure MRI. This in turn wreaks havoc as far as Bundler is concerned. I’m probably one of the least favorite posters on the Bundler issue tracker due to the number of times I’ve pointed out problems with using Bundler in a mixed MRI/JRuby environment; in short, it is a tricky issue, and nobody sane would do it unless there were no viable alternatives.

Cabybara to the rescue, again

Right now I have a working acceptance test suite that runs on both my local development machine (Mac OS X) and also on my deployment server (Fedora). Almost all of the tests run through rack-test, and they run quickly. Tests which require JavaScript/AJAX run through Culerity, which is an interface to Celerity, which is itself a JRuby wrapper for HtmlUnit, which is a headless browser written in Java.

This set-up works, but the dependency on JRuby and the problems it causes for Bundler are an annoyance.

Nevertheless, the driver model of Capybara and the consistent API allow me to consider switching to alternative back-ends without having to sweep over my entire test suite making changes.

  • EnvJS (GitHub link) seems to be one interesting option. There is a capybara-envjs driver that is based on rack-test and which uses EnvJS to provide a headless browser environment in which to run JavaScript.
  • Then there’s Akephalos, which I’d never even heard about until I read this post; it’s apparently Jonas Nicklas’ favorite driver right now (Jonas is the author of Capybara), and somehow manages to build on top of the Java HtmlUnit without needing to go through JRuby. I’m going to have a look into it and will be curious to see how it does this.

The great thing about Capybara is that you’re free to try out alternatives like this with a very low commitment. Flip a switch and try it out, if you’re not happy, just flip it back.