2013/04/15

Unit testing Javascript- why and how

Big delay for this post - the back-end programmer got tangled up in, well, back-end stuff.
However, one of the beautiful properties of back-end code is that it is easily testable (if you make it so).

This made me thinking - up until now my basic Javascript skills did not include "unit testing". The benefits of testing Javascript are the same if you tested C#, Java, or Python code:

  • test-driving your code leads to a better design
  • good test coverage builds trust in the code
  • good tests take the fear away - if a test breaks, you (should) know what went wrong and start over

The question is - how do I get those same advantages when I write the dreaded Javascript? What tools are there?

I looked at several libraries, but there are two that caught my attention.
QUnit is worth your attention if you are already familiar with any xUnit framework. The syntax is very intuitive, there are different asserts for almost anything. And it is supported by the jQuery team so there is a guarantee for quality. What I did not like was the lack of support for mocking. Sure, there are separate libraries for that, but I wanted something... simpler. The other thing that made me look for something else was the fact that I had to create HTML "containers" for my test suites - not a big fan of it.

The other one is Jasmine. At first it looks a bit.. weird. There are describe()-s, and it()-s, and you don't have asserts but expect()-ations. After a bit, though, it started to grow on me. For several reasons:

  • There are a lot of expectations already implemented, but if you wanted something custom, you could create custom ones fairly easy with custom matchers.
  • Mocking - comes out of the box in the form of "spies". And you can even mock setInterval and setTimeout.
  • No need to create HTML "containers". Not that you couldn't.

That last one led me to another point - if I don't have a HTML file, how do I run my tests? Jasmine is (I am told) widely adopted by the Ruby community and there are (as I am told) gems that you could use to include your tests in your CI process.
For .Net - not so much. With a little exception - a Visual Studio add-on called Chutzpah. This add-on not only provides a headless browser for executing the tests, it also adds MSBuild targets. As I later discovered, it even supports QUnit tests. It is a valuable tool for integrating your Javascript tests into the development and build process.

Here I will not go into much more detail on how to set up your environment. Because when it's done, it's done. And aside from small tweaks you shouldn't need to touch it. But how exactly do you write your unit tests?

I will go back to the Conway's Game of Life examples from the last post.
Remember the Cell class? In the basic rules of GoL a cell can be either dead or alive:
Let's write the unit tests using Jasmine:

describe('Cell', function () {});

What I created with the snippet above is just the definition of something I called "Cell" (although I could have called it "The basic GoL cell"). So far this line in itself doesn't do anything except let us know that we are going to see a few tests about this "Cell".

describe('Cell', function () {
    it('is dead by default', function () {
        var cell = new Cell();
        expect(cell.IsAlive()).toBe(false);
    });
});

Now, it() defines our test - what we called "cell" should be dead. And you can see a very simple expect()-ation.

And there you have it. If you run this test against the Cell object, it should pass:

var Cell = function (isAlive) {
    var _isAlive = isAlive != undefined ? isAlive : false;

    this.IsAlive = function () {
        return _isAlive;
    };

    this.IsDead = function () {
        return !_isAlive;
    };
};


Cheers!