Last week I went on a bootcamp with my team to build a prototype for an upcoming web app. We decided on a test-driven approach to the project. I feel like this is one of the best decisions we’ve ever made. It might be slow to get into, but once you are you never want to go back to regular ‘ol programming style. Never I’ve had so much faith in the code I’ve written. It also really is a huge step forward in productivity.
There are a couple of ingredients to the automated testing workflow I’ve come to love:
- Jasmine-jquery - Some sweet Jasmin selectors and fixture support
- CoffeeScript - Programmer happiness++
- Jasmine Headless Webkit - Outputs feedback into the terminal
- Guard - Makes it possible to run tests directly when you save them
Jasmine Headless Webkit uses a QTWebKit Widget to run the tests in. Therefor we’ll need QT on our system. If you’re on OSX, the easiest way to install it is via Homebrew:
$ brew install qt
If you’re on another OS check the Jasmine Headless Webkit website and look in the Qt 4.7.X section for instructions.
Setting up the Ruby environment
If you haven’t already done so, install RVM by reading the installation documentation. Now create a new RVM configuration by running the following commands in a terminal in your project directory:
$ rvm use 1.9.2@myproject --create
$ echo 'rvm use 1.9.2@myproject' > .rvmrc
This will create and use an enclosed Ruby 1.9.2 environment within your project and will make sure it will use the correct Ruby version every time you enter your project via the command line. Try this by
cd .. and
cd myproject. The first time, you’ll be asked to confirm you want to use the
.rvmrc file we just created.
We will now create a Gemset using Bundler. With Bundler we will create a “Gemfile” which will list the gems needed for our project. Installing it is as easy as running:
$ gem install bundler
Now create a file called
Gemfile (yes, without an extension) in your project directory root and add the following lines to it:
Save the file and run the following command:
This will download and install the gems and their dependencies to a contained gemset within the RVM environment. It will also create a new file called “Gemfile.lock” which is kind of a binary file containing the gems.
We’re now ready to configure our environment. Let’s get started!
Setting up Jasmine
Jasmine comes with an
init function which will set up a directory structure for you. Run the following command from your project root directory:
$ bundle exec jasmine init
With bundle exec, the jasmine executable will be called from the gemset.
Download the latest release of jQuery and drop it into
We’re now going to edit the Jasmine configuration file. Open up
This ensures that jQuery is picked up at the start so we can use it in our tests. We’ll also tell Jasmine to look for .coffee files since Jasmine Headless Webkit supports CoffeeScript!
You could actually start testing right now but there’s one more thing..
Configuring Guard to automate testing
Guard lets us start a process when filesystem events occur. In our case, Jasmine will run the tests when we edit them. To enable Guard for our project, run the following command:
$ guard init jasmine-headless-webkit
This creates a “Guardfile” with all configuration we need. To start watching your project, simply run
guard from your project root. This will automatically run all tests when you save a spec file.
Bonus (Growl notifications): Add the gems
growl_notify to your Gemfile and run
bundle to enable Growl notifications for Guard!
Let’s test our testing setup
Finally we’ve got our testing environment all set up so it’s time to test if our setup works.. The actual writing of tests is beyond the scope of this tutorial but for now I’ve provided a spec and an implementation file. I might do an in-depth testing tutorial soon.
If you’ve run
guard already, you should see that the 5 tests that came with Yasmine passed. Once you’ve created above files there should be 8 passing tests.
We had to do quite some research to find the optimal testing workflow and I believe we succeeded in finding our way in this. I hope this setup will make the awesome test-driven development that everyone should practice somewhat easier.
If you’d like to learn more about this workflow, you’ll like these resources: