Friday, November 11, 2011

Jasmine Backbone.js Revisited

‹prev | My Chain | next›

Up tonight, I get started revisiting my jasmine testing setup for Backbone.js. Sadly, I have completely forgotten how it was setup. Luckily, I write down everything I do in this blog series.

I first implemented test back in September. I have a two step process in place. First, I generate a fixture file that contains the start page of my app. Then I run a server to test the application loaded on that page by making use of the jasmine ruby gem.

It is a fairly nice setup in that I am testing the application as applied to the real start page. The only missing piece is actual server interaction. Luckily there is sinon.js, which can stub out XHR requests.

There may be better ways of doing this, but, before exploring them, I would like to get my test suite passing again and possibly write a few new tests.

To start the jasmine server, I run rake jasmine:
➜  calendar git:(jasmine) rake jasmine
your tests are here:
  http://localhost:8888/
[2011-11-11 22:54:53] INFO  WEBrick 1.3.1
[2011-11-11 22:54:53] INFO  ruby 1.9.2 (2011-07-09) [x86_64-linux]
[2011-11-11 22:54:53] WARN  TCPServer Error: Address already in use - bind(2)
[2011-11-11 22:54:53] INFO  WEBrick::HTTPServer#start: pid=31207 port=8888
Ah, I recall that "Already in use" message. I have no idea why it comes up, but I know it can be safely ignored. Possibly I need to update a gem or ruby. I will worry about that another day.

For now, I point Firefox (I recall Chrome choking on specs for no apparent reason) to http://localhost:8888 and am greeted with:


Hrm... Well, I suppose that is not too bad. There has been nearly two months worth of development on my Backbone application since I last ran the test suite.

Ooh! Wait a second, I need to regenerate that fixture file. For that, I am using a very simple expresso test that runs my express.js app, requests the homepage, then writes the response to a fixture file:
// Force test environment
process.env.NODE_ENV = 'test';

var app = require('../app'),
    assert = require('assert'),
    fs = require('fs');

module.exports = {
  // ...
  'generate fixture': function() {
    assert.response(app,
      { url: '/' },
      function(res) {
        fs.mkdir('spec/javascripts/fixtures', 0775, function() {
          fs.writeFile('spec/javascripts/fixtures/homepage.html', res.body);
        });
      });
  }
};
The benefit derived from requesting the page from a running express server is that the Jade templates in the application have been compiled to HTML. At this point, I might consider dumping jade since my HTML has gotten smaller and smaller as the responsibilities of my Backbone app have grown. I will defer that for another night as well.

For now, I just hope that generating an updated fixture will produce a better test run. So I run my expresso test suite / fixture generator:
➜  calendar git:(jasmine) expresso
The "sys" module is now called "util". It should have a similar interface.

   100% 2 tests
And then check the results by reloading my browser:


Oh, man! I have more than doubled the number of failures. Meh. Serves me right for neglecting my test suite.

Examining the spec suite, I notice that I have hard-coded my dates for September:
describe("Home", function() {
  var server,
      couch_doc = {
        "_id": "42",
        "_rev": "1-2345",
        "title": "Get Funky",
        "description": "asdf",
        "startDate": "2011-09-15"
      },
      doc_list = {
        "total_rows": 1,
        "rows":[{"doc": couch_doc}]
      };
As can be seen from the URL of my failing spec run, the Routing code in my app is kicking in and it believes that we are in November. So I change the startDate attribute to "2011-11-15" and update the first failing spec to November as well:
  describe("appointments", function() {
    it("populates the calendar with appointments", function() {
      expect($('#2011-11-15')).toHaveText(/Get Funky/);
    });
  });
With that, my failure message has changed:
That is actually quite encouraging. The message:
Expected '<td id="2011-11-15"><span class="day-of-month">15</span></td>' to have text /Get Funky/.
Means that the calendar is being drawn correctly. I recently switched to drawing the calendar HTML over to Backbone (rather than doing it on the server). So at least I know that the calendar drawing portion of the application is working.

Checking Firebug, I notice that there are no errors. Also checking the jasmine server, I do not see any error either. Still, I suspect that a stray XHR request is getting through.

And indeed, that was the cause. I now have to stub out all requests to anything matching the URL /appointments:
    // populate appointments for this month
    server.respondWith('GET', /\/appointments/,
      [200, { "Content-Type": "application/json" }, JSON.stringify(doc_list)]);
    server.respond();
With that, I finally have my very simple first test passing:


With a little progress under my belt, I call it a night. I will pick back up tomorrow working through the remaining failures.

Day #202

No comments:

Post a Comment