Erik's Engineering

something alliterative

Guard Remembers

The Problem

At Moxie, we not only build a web app for people to use, we also have an API that can be used to access that app. It's used for a bunch of external applications - a Dropbox-like file syncer, some kind of integration with Outlook and a couple native mobile clients.

In order to make sure we don't break all those external users, we have tests of our own API. These tests live in separate files and we've already begun versioning them so that we can drop api/v2 in there once we realize we have to make breaking changes to api/v1.

The problem is that we always forget to run the API tests before we commit. The full test suite takes hours to complete so folks don't do that before they push their branches, or even before they merge them into master. You're supposed to go run all the individual test files for anything you might reasonably have been expected to break, but almost everyone forgets to do that pretty regularly. Jenkins still runs the tests and fails the build so customers are not impacted, but build breakage is embarassing.

Guard to the Rescue

I've been setting up our apps to use guard to run tests any time something changes. It saves you a second or two after every save when you'd otherwise have to switch to your terminal and hit ctrl-p [enter]. This is all win all by itself, but did you know you can have guard run multiple test files for a given file change? Here's a line from one of our Guardfiles:

watch(%r{^app/models/(.+)\.rb$}) { |m|
    ["test/unit/#{m[1]}_test.rb", "test/api/v1/#{m[1]}s_api_test.rb"] }

Notice how I just returned an array of files inside that block instead of a single file name? That's all there is to it. Pretty simple. Now any time a model changes, both the unit test and the API test will run. I hooked the controllers up the same way. Change a controller and both the functional and API tests run.

One gotcha: I'm using guard-test instead of guard-minitest. The output isn't quite as pretty and under the hood I think it's relying on minitest's backwards compatibility mode. Recent versions of guard-minitest add an explicit dependency on the minitest gem, rather than letting you use the one that comes with MRI. That lets them target specific versions of minitest, but it breaks our tests pretty badly for some reason. We'd probably be better off rooting out that implicit version dependency and switching to the gem, but I promised not to make big sweeping changes during my last week :)


Published on 08/08/2013 at 13h07 under , . Tags , , ,

Comment Guard Remembers

Powered by Typo – Thème Frédéric de Villamil | Photo Glenn