Experience with Poltergeist and PhantomJS Testing

Let's go down the long path of integration testing, where teams seem scared to venture.

I've worked on a few teams where we used Cucumber or plain capybara for our integration testing layer, and that has always been backed with capybara-webkit as the JS driver for the headless browser. In this article we'll explore the differences between capybara-webkit and phantomjs as a driver for capybara.

Examining capybara-webkit

Until more recently, I believe phantomjs just wasn't as reliable as capybara-webkit and that was the biggest motivating factor for not using it (correct me if I'm wrong).


Installing capybara-webkit is not as easy as it should be. Installation on your computer requires a build of QT to link against, and QT is a massive download and install.

Additionally, installation and configuration on your CI server requires a headless X server, such as Xvfb. There are more tools to install and more configuration with capybara-webkit. Gems such as headless help a bit with the configuration in your Rails app, but the general requirements are still there.


Capybara-webkit provides a JS enabled headless browser, allows you to render the page to HTML or an image and supports the vast library of capybara features.

Examining phantomjs and poltergeist

The poltergeist gem provides a phantomjs driver for capybara, same goal as capybara-webkit. Phantomjs is also built on top of the webkit rendering engine, but that's about where the similarities between the two projects end.


Installation of phantomjs is much quicker on a Mac, as a QT installation is not required to build the project. On our CI server we're running CentOS, which required sudo access to add a yum repo for installation of phantomjs.

name=Copr repo for phantomjs owned by stevenmerrill

After the yum repo was installed, installing phantomjs on our CI server was fairly simple.

sudo yum install phantomjs


Phantomjs offers all the same features as capybara-webkit, but with a much easier installation. Additionally however, I really like the option to raise an error in Ruby when there is an error in the headless browser.

Exception Handling

A great example of how this is beneficial could be testing a page that happens to load a JS library twice, or even a simple parse error in JS. Phantomjs will raise a Ruby exception, with a backtrace into your issue, allowing you to much more easily track down the problem.

With capybara-webkit, your expectation in capybara would fail due to an element not being present on the page, but you would have no clue why. In the past I've debugged scenarios like this by saving the HTML of the page, opening a browser on the port of the currently running Capybara server, or switching to Selenium and a pause statement to examine the contents while the test runs.

Network Traffic

Another awesome feature to make use of was inspecting network traffic. In my capybara step definition, I could inspect all the requests the phantomjs browser had made, including request headers, response headers and the respond body, with the following command:


With this command I noticed that our test suite was loading the Bootstrap CSS library from a CDN in every test, and was able to properly configure VCR in our test project to cache the contents to speed up our tests.

You could also make great use of this to inspect Ajax calls made during your JS browser session and ensure that the server response was what you expected.

Phantomjs just provided a stellar debugging experience overall compared to capybara-webkit.


The actual conversion from one web driver to another in our project was actually pretty painless. We did not have any tests fail, the configuration was straight forward, and configuring the CI server was easy.

I hope that helps convince you and your team to take poltergeist for a spin in your test suite and see how much time you can save debugging those painful scenarios that fail.

Displays images in a grid, with individual pages optionally describing the image in detail, or displaying more images. Images have a max-width of 400 pixels by default.

Our Products

It takes one to know one - we've walked the walk by building our own products that customers love.

Ready to have a chat?

Contact us to chat with our founder
so we can learn about you and your project.