CSS Regression Testing with Resemble.js

Roughly a year ago Alex Sexton's Smashing Magazine article highlighted a new role emerging amidst the increasing complexity of front-end work in a responsive world: Front End Ops. Since that article was published, there's been an entire conference devoted to the subject, and folks like Chris Ruppel have evangelized similar roles and supporting tools to the Drupal community. Sitting in Ruppel's talk at BadCamp last year was my first exposure to the idea of front-end ops. I'm a big fan of automation and consistency; I'm also relentlessly tinkering with my local development tool chain to find ways to work more efficiently. Naturally, I was intrigued, and needed to learn more. It's an ongoing journey, as front-end tooling is changing incredibly rapidly, but one tool I've recently completely fallen in love with is Resemble.js.

In a nutshell, Resemble.js takes two images, and generates a third that highlights the differences between the source images. Why is that exciting? With the right support tools, it allows us to do CSS regression testing via image analysis. I've created a simple example of the technique below, using our work on lullabot.com. In a pull request, I tweaked our sass to replace the site's Proxima Nova font with Helvetica Neue (typographic sensibilities be damned). Although it might seem innocuous, the change causes all sorts of havoc with spacing. In addition, my changes caused our rotating photo gallery to disappear from the rendered page. Below, you can see before-and-after versions of the site, with the production version on the left and the test server on the right.

The changes introduced by the pull request are fairly subtle if you're relying on manual comparison between browser tabs. A slightly different font, some spacing changes, and a missing photo gallery (rather than an obviously broken one) would be easy to miss for a developer doing a quick hit-and-run QA pass. Thankfully, using resemble.js, we don't have to rely on our typographic sensibilities to notice this regression.

To demonstrate how easy it is to find these regressions once resemble.js has compared them, here is what the diff output looks like:

It's readily apparent that something is amiss. Taking full screen screen shots like this isn't exactly a best practice, because it is likely to yield false positives and hard to read diff images. However, it does a decent job at catching our attention when there are large scale issues.

We're using this basic approach on several projects right now to speed up the QA process. We use resemble.js with PhantomJS to capture screenshots from a live site and an automatically-built test site for each pull request. These screen captures can be taken at any path, and any resolution we'd like to test. The resulting image files are then referenced in an automated github comment generated by our build tool, Tugboat. This gives us a way to quickly scan a pull request to see if we've accidentally introduced any visual regression bugs.

For more fine-grained visual regression testing, I'd recommend Phantom CSS. PhantomCSS, another tool from the folks at Huddle, uses resemble.js under the hood for image analysis and comparison too. PhantomCSS can target specific page components with css selectors, making the tests more atomic and the results easier to digest.

What's the easiest way to get started using resemble.js for your projects?
I've written a small command line utility in node.js to wrap up this functionality in an easy to use tool. Assuming you already have nodejs and phantomjs installed, you can make use of it by checking out the git repository and running npm install to grab the required dependencies. Additionally, in order to be able to configure the settings of the diff image, a patch is required to integrate the latest resemble.js code. Screenshot comparisons can then be generated by running node resemble http://example.com http://stg.example.com.

The actual code that creates the images is relatively straightforward, and weighs in at 130 lines of code. Using node.js to write small command line utilities like this is a fun and easy way to create and customize your front-end ops workflow. I'm looking forward to writing more small tools like this to help make all of our lives a little bit easier.