June 15, 2013 3 Comments
One of the things I really loved about Rails in the early days was that it introduced me to the concept of autotest – a script that would watch your file system for changes and then automatically execute your unit tests as soon as you change any file.
Because the unit test suite typically executes quickly, you’d tend to have your test results back within a second or two of hitting save, allowing you to remain in the editor the entire time and only break out the browser for deeper debugging – usually the command line output and OS notifications (growl at the time) would be enough to set you straight.
Guard is a simple ruby gem that scans your file system for changes and runs the code of your choice whenever a file you care about is saved. It has a great ecosystem around it which makes automating filesystem-based triggers both simple and powerful. Let’s start by making sure we have all the gems we need:
gem install jasmine jasmine-headless-webkit guard-jasmine-headless-webkit guard \ guard-livereload terminal-notifier-guard --no-rdoc --no-ri
Next up we grab guard-livereload, which enables Guard to act as a livereload server, automatically running your full suite in the browser each time your save a file. This might sound redundant – our tests are already going to be executed in the headless webkit environment, so why bother running them in the browser too? Well, the browser Jasmine runner tends to give a lot more information when something goes wrong – stack traces and most importantly a live debugger.
Finally we add the terminal-notifier-guard gem, which just allows guard to give us a notification each time the tests finish executing. Now we’ve got our dependencies in line it’s time to set up our environment. Thankfully both jasmine and guard provide simple scripts to get started:
jasmine init guard init
And we’re ready to go! Let’s test out our setup by running `guard`:
What you should see at this point is something like this:
We see guard starting up, telling us it’s going to use TerminalNotifier to give us an OS notification every time the tests finish running, and that it’s going to use JasmineHeadlessWebkit to run the tests without a browser. You’ll see that 5 tests were run in about 5ms, and you should have seen an OS notification flash up telling you the same thing. This is great for working on a laptop where you don’t have the screen real estate to keep a terminal window visible at all times.
Now try editing that file and hitting save – nothing happens. The reason for this is that the Guardfile generated by `guard init` isn’t quite compatible out of the box with the Jasmine folder structure. Thankfully this is trivial to fix – we just need to edit the Guardfile.
If you open up the Guardfile in your editor you’ll see it has about 30 lines of configuration. A large amount of the file is comments and optional configs, which you can delete if you like. Guard is expecting your spec files to have the format ‘my_spec.js’ – note the ‘_spec’ at the end.
To get it working the easiest way is to edit the ‘spec_location’ variable (on line 7 – just remove the ‘_spec’), and do the same to the last line of the `guard ‘jasmine-headless-webkit’ do` block. You should end up with something like this:
Once you save your Guardfile, there’s no need to restart guard, it’ll notice the change to the Guardfile and automatically restart itself. Now when you save PlayerSpec.js again you’ll see the terminal immediately run your tests and show your the notification that all is well (assuming your tests still pass!).
So what are those 4 lines inside the `guard ‘jasmine-headless-webkit’ do` block? As you’ve probably guessed they’re just the set of directories that guard should watch. Whenever any of the files matched by the patterns on those 4 lines change, guard will run its jasmine-headless-webkit command, which is what runs your tests. These are just the defaults, so if your JS files are not found inside those folders jus update it to point to the right place.
The final part of the stack that I use is livereload. Livereload consists of two things – a browser plugin (available for Chrome, Firefox and others), and a server, which have actually already set up with Guard. First you’ll need to install the livereload browser plugin, which is extremely simple.
Because the livereload server is already running inside guard, all we need to do is give our browser a place to load the tests from. Unfortunately the only way I’ve found to do this is to open up a second terminal tab and in the same directory run:
This sets up a lightweight web server that runs on http://localhost:8888. If you go to that page in your browser now you should see something like this:
Just hit the livereload button in your browser (once you’ve installed the plugin), edit your file again and you’ll see the browser automatically refreshes itself and runs your tests. This step is optional but I find it extremely useful to get a notification telling me my tests have started failing, then be able to immediately tab into the browser environment to get a full stack trace and debugging environment.
That just about wraps up getting autotest up and running. Next time you come back to your code just run `guard` and `rake jasmine` and you’ll get right back to your new autotesting setup. And if you have a way to have guard serve the browser without requiring the second tab window please share in the comments!