Wednesday, September 7, 2011

Lame Attempts at Backend Testing a Backbone App

‹prev | My Chain | next›

I have made quite a bit of progress on my Funky, Funky Calendar Backbone.js application these past few days. I have definitely reached the point at which I am going to need some tests to help me add new features and refactor old features without breaking things. But how to test?

Hrm...

Well, there is a project called jasmine-node. I have done quite a bit of front-end testing with Jasmine in the past. Perhaps that is a good place to start:
➜  calendar git:(master) npm install jasmine-node -g
/home/cstrom/local/node-v0.5.5/bin/jasmine-node -> /home/cstrom/local/node-v0.5.5/lib/node_modules/jasmine-node/bin/jasmine-node
coffee-script@1.1.2 /home/cstrom/local/node-v0.5.5/lib/node_modules/jasmine-node/node_modules/coffee-script 
jasmine-node@1.0.8 /home/cstrom/local/node-v0.5.5/lib/node_modules/jasmine-node 
Usage seems straight forward enough:
➜  calendar git:(master) jasmine-node               
USAGE: jasmine-node [--color|--noColor] [--verbose] [--coffee] directory

Options:
  --color            - use color coding for output
  --noColor          - do not use color coding for output
  -m, --match REGEXP - load only specs containing "REGEXPspec"
  -i, --include DIR  - add given directory to node include paths
  --verbose          - print extra information per each test run
  --coffee           - load coffee-script which allows execution .coffee files
So I create a sanity check to make sure that I can run tests. In spec/appointment.spec.js, I add:
describe("Sanity", function() {
  it('should pass', function(){
    expect(1+2).toEqual(3);
  });
});
To run that spec, I then call jasmine-node from the command line:
➜  calendar git:(master) ✗ jasmine-node spec --verbose
Started
.

Spec Sanity
  it should pass
Finished in 0.004 seconds
1 test, 1 assertion, 0 failures
That is all well and good, but I would like to be able to write Jasmine specs to describe the Backbone application itself. For instance, a simple Model test might be:
describe("Appointment", function() {
  it("uses the /appointments url-space", function () {
    var it = new Appointment;
    expect(it.urlRoot).toEqual("/appointments");
  });
});
But how can I run that with node-jasmine? Don't I need a browser?

Ahhhh. Dang it. Now I get it. The jasmine-node package is for testing backend code, not frontend stuff. Duh.

Ultimately, I think I will require some combination of the jasmine gem (to run a test web server), jasmine-jquery (to load html fixtures) and jasmine proper. But first, I need to be able to generate HTML fixtures from the backend. For that, I need a quick means to exercise the server and do simple GETs. I might be able to get jasmine-node to do this, and I have already done something similar with vows.js, but I think I would like to give expresso a go.

So I install via NPM:
➜  calendar git:(master) ✗ npm install -g expresso

> expresso@0.8.1 preinstall /home/cstrom/local/node-v0.5.5/lib/node_modules/expresso
> make deps/jscoverage/node-jscoverage

cd deps/jscoverage && ./configure && make && mv jscoverage node-jscoverage
checking for a BSD-compatible install... /usr/bin/install -c
...
make[1]: Leaving directory `/home/cstrom/local/node-v0.5.5/lib/node_modules/expresso/deps/jscoverage'
/home/cstrom/local/node-v0.5.5/bin/expresso -> /home/cstrom/local/node-v0.5.5/lib/node_modules/expresso/bin/expresso
/home/cstrom/local/node-v0.5.5/bin/node-jscoverage -> /home/cstrom/local/node-v0.5.5/lib/node_modules/expresso/deps/jscoverage/node-jscoverage
expresso@0.8.1 /home/cstrom/local/node-v0.5.5/lib/node_modules/expresso
Once that is done, I create a basic test to assert that the homepage references backbone.js (presumably in a <script> tag):
var app = require('../app'),
   assert = require('assert');

module.exports = {
  'is a backbone.js app': function(){
    assert.response(app,
      { url: '/', timeout: 500 },
      { body: /backbone.js/ });
  }
};
I save that in the ./test sub-directory so that expresso will run that test by default:
➜  calendar git:(master) ✗ expresso

   100% 1 tests
Yay! That was surprisingly easy. Just to make sure that I am actually performing a real test, I break the assertion:
var app = require('../app'),
assert = require('assert');

module.exports = {
  'is a backbone.js app': function(){
    assert.response(app,
      { url: '/', timeout: 500 },
      { body: /old_fashoned.js/ });
    }
};
And, sure enough, the test now fails as expected:
>➜  calendar git:(master) ✗ expresso

   uncaught: AssertionError: is a backbone.js app. Invalid response body.
    Expected: /old_fashoned.js/
    Got: '<!DOCTYPE html 
...
Wow. I have to admit that expresso is pretty darn nice for testing express.js applications. I think I will call it a night there. Up tomorrow, I hope to take the response from one of those tests, save it to a fixture and use that in a jasmine-gem test.


Day #136

No comments:

Post a Comment