Yesterday I had me a big breakthrough in my Backbone.js testing with jasmine. By replacing one, tiny snippet of non-idiomatic routing code with the "backbone way" equivalent, I magically eliminated a number of annoyances.
In particular, I now have tests failing when I intentionally break my application's routing. Unfortunately, the failure message is non-obvious. The failure indicates that appointments are not being populated on my calendar application. In fact, they are not being populated because the routing has failed, but it will take a bit of digging each time I cause this failure.
So today, I hope to test things a little more directly. Given the I am creating the application in my spec setup:
beforeEach(function() {
// ...
window.calendar = new Cal($('#calendar'));
// ...
});
Then, in my tests, I can check to see that the application auto-redirects to the current month:describe("routing", function() { it("defaults to the current month", function() { var today = new Date() , year = today.getFullYear() , m = today.getMonth() + 1 , month = m<10 ? '0'+m : m; expect(Backbone.history.getFragment()) .toEqual("month/" + year + "-" + month); }); });That passes, but, when I remove the
true
second argument to Backbone.history.navigate()
in the application's default route: var Routes = Backbone.Router.extend({
// ...
_setDefault: function() {
console.log("[setDefault]");
var month = Helpers.to_iso8601(new Date).substr(0,7);
Backbone.history.navigate('#month/' + month); //, true);
},
// ...
});
Unfortunately, that does not fail. Ah, of course... I am testing that the default route does something. What I try to break is the subsequent triggering the appropriate route. So the default route is firing, but is not triggering the applicable route.For that, I need to add a secondary test to verify that default route sets the application date in addition to redirecting:
describe("routing", function() {
it("sets the date of the appointment collection", function() {
var appointments = window.calendar.appointments;
expect(appointments.getDate())
.toEqual("2011-11");
});
});
With, that, I get my desired failure:I can then replace the
true
argument to ensure the subsequent route is triggered and now my test passes:If you cannot make a test fail by changing one line (or even one word), then the test is useless. I was a bit worried at first about the initial passing test. Once I realized I was testing two different things (the route firing and the route triggering a subsequent route), I got a failing test. I now feel much better about my test suite.
Failure: it's a good thing when testing.
Day #214
No comments:
Post a Comment