Introduction
While writing some CoffeeScript field validation functions for a client, I realized that I really needed a way to test the functions outside of the browser. Initially, I just hacked together my own simple test framework, which got the job done. However, I decided it’d be better to use a more full-featured framework. I settled on Jasmine, a behavior-driven development (BDD) testing framework for Javascript.
The remainder of this article describes how I am currently using Jasmine. There are loads of other ways to use this excellent tool; this is just what I am doing with it. I’m using Jasmine with node.js, at the command line. Jasmine also supports integration with Ruby, Rails, Django, and Java, among others.
Preparation
Node.js and npm
First, you’ll need the node.js Javascript framework. (Of course, since you’re using CoffeeScript, you already have that, right?) I also recommend installing the Node Package Manager (npm). This document assumes you’re using npm, since it makes things a whole lot easier.
Jasmine-Node and your test directory
Once you have npm installed, create an empty directory to hold your tests. Within that directory, install Jasmine-Node.
1 2 |
|
You’ll end up with a node_modules
subdirectory.
Rake, Buildr, Make, whatever
Let’s make it easy to invoke the tests by creating a Rake or make build file. I’ll show examples of both here. However, since I’m using Rake, I won’t be mentioning make from here on.
First, the Rakefile
:
1 2 3 4 5 6 7 |
|
Here’s the GNU make equivalent:
JASMINE_NODE = node_modules/jasmine-node/bin/jasmine-node
test:
$(JASMINE_NODE) --coffee --verbose spec
Writing tests
What I’m testing
Let’s assume I have a CoffeeScript file called util.coffee
, containing
some utility functions I want to test. For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
Jasmine tests
A brief overview
I’m not going to give a complete overview of Jasmine here; I assume you can read the Jasmine web site to understand more about its suites and specs, matchers, spies (mockers) and other capabilities. I’m only going to mention the few Jasmine capabilities necessary for this article.
There are four main concepts that matter here:
- Test suites
- Tests
- The
expect
function - Matchers
In Jasmine, a test suite groups individual tests and is defined with a
describe
function wrapper. Each test within a suite is encapsulated within
an it
function. In Javascript, a suite might look like this:
1 2 3 4 5 |
|
In CoffeeScript, that same test is much more readable:
1 2 3 |
|
The expect
call simply takes the value you want to test–in this case, the
result of a call to meaningOfLife()
. The object it returns encapsulates that
value and provides a series of matchers, such as toEqual()
, that can be
used to test that result.
The actual tests
And now, the actual tests. Jasmine expects CoffeeScript tests to be in
files that end with .spec.coffee
. So, these tests will be in
spec/Validations.spec.coffee
. The test implementation is straightforward:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
|
Note that I’m using objects of test data to drive each test. That’s obviously
not necessary; you could just as easily make multiple expect
calls.
Running the tests
Running the tests produces the following output:
$ rake
(in /home/bmc/src/coffeescripts/coffeetest)
node_modules/jasmine-node/bin/jasmine-node --coffee --verbose spec
Started
...
Spec Validations
it should properly validate email addresses
it should properly validate zip codes
it should properly validate phone numbers
Finished in 0.002 seconds
1 test, 37 assertions, 0 failures
You can get less verbose output simply by omitting the --verbose
argument
to Jasmine. (I prefer the verbose output.)
If I deliberately break one of the tests, to cause a failure, I get output like this:
$ rake
(in /home/bmc/src/coffeescripts/coffeetest)
node_modules/jasmine-node/bin/jasmine-node --coffee --verbose spec
Started
..F
Spec Validations
it should properly validate email addresses
it should properly validate zip codes
it should properly validate phone numbers
Error: Expected false to equal true.
at [object Object].<anonymous> (/home/bmc/src/coffeescripts/coffeetest/spec/Validations.spec.coffee:73:34)
Finished in 0.004 seconds
1 test, 37 assertions, 1 failure
rake aborted!
Command failed with status (1): [node_modules/jasmine-node/bin/jasmine-node...]
/home/bmc/src/coffeescripts/coffeetest/Rakefile:13
(See full trace by running task with --trace)
By default, on an ANSI-capable terminal or terminal emulator, the output is colorized (not shown here).
Conclusion
Jasmine is an excellent Javascript test framework. Mix it with CoffeeScript, and you get some serious deliciousness.