Friday, May 24, 2013

A Critique of the Thoughtworks Tech Radar on Javascript Testing

The Thoughtworks' Tech Radar has come out again and there is no change in the recommendation on Javascript testing.

The radar recommends to "Adopt Jasmine paired with Node.js". This is very specific advice. It's not "Adopt Javascript testing paired with Node.js" but a specific tool, Jasmine. Compare this with more general advice such as "Adopt CSS Frameworks" or "Promises for asynchronous programming". Nothing specific there and, hence, nothing wrong.

There is no motivation as to why we should adopt Jasmine but, if we look at the TTF from October 2012(PDF), we can read:

The cream of the crop for out-of-browser testing is currently Jasmine. Jasmine paired with Node.js is the go-to choice for robust testing of both client- and serverside JavaScript.

"The cream of the crop"? This is certainly not the case! Jasmine is an elegant testing framework similar Ruby's RSpec but, it is not "the cream of the crop"! It has one major drawback. It sucks at testing asynchronous code! And, since asynchronous code is a central theme in Javascript programming we should not use Jasmine! There are at least two better alternatives:

Example

In this example I want to test a simple asynchronous sort function called sleepsort, you can read more about it in Writing a Module.

The function signature looks like this:

// Sleepsort takes an array of numbers and calls callback(result)
// with the sorted array as the only argument
function sleepsort(array, callback) {
...
}

Testing this with Jasmine will look something like this:

it('sorts the array', function () {
  runs(function() {
    this.result;
    sleepsort([1, 3, 2, 7], function(result) {
      this.result = result;
    });
  });

  waits(1000); // Wait one second then check the rsult

  runs(function () {
    expect(this.result).toEqual([1, 2, 3, 7]);
  });

});

This is horrible! Compare this to Mocha, with should.js assertions:

it('Sorts the array', function(done) {
  sleepsort([1, 3, 2, 7], function(result) {
    result.should.eql([1, 2, 3, 7]);
    done();
  });
});

Thank you, Sir, may I have another!

Indeed you may, here it is with Buster.js, with Object style syntax:

"Sorts the array": function (done) {
  sleepsort([1, 3, 2, 7], function(result) {
    assert.equals(result, [1, 2, 3, 7]);
    done();
  });
}

Both Mocha and Buster.js send in a done function to call when the execution has finished. Elegant, and above all, crystal clear.

It is very obvious to me that Jasmine no longer is "the cream of the crop" of Javascript testing. But, what do I know, perhaps it was a copy-paste error.

I've done my duty, now I can go to bed!

Duty Calls from XKCD

No comments: