Общо показвания

февруари 13, 2012

Tests running in both browser and nodejs

Following my post about developing on cloud9 and running your tests in both node.js and browser, this post will show how I had to make some sacrifices to allow proper tests constructions and support for assert testing that works on both node and browser.

First - the screenshots!

Tests run in browsers


Same tests run in node

The 'test runner' (debug name designated to 'AllTest' in the screenshot) is exactly the same file (see the post mention in the beginning of this one), the only difference is the run script: we need to use run-in-node.js and run-in-browser.js respectively, which is pretty easy to maintain.

I spend a good part of the Sunday trying to figure out a way to use a test framework that works exactly the same in both the browser and node.js and on top of that can work just fine with requirejs (which I use on the server and on the browser with amdefine and rjs on the server). I have tried several but I either couldn't make it work with requireJS or run the same tests in both environments. The closest thing to what I imagined a test suite would be was Vows. Unfortunately it runs only in node and the code depends on process, file and other objects not found in the list of host objects in the browser.

Never the less, the way one structure the tests in Vows was what I was looking for. The only thing I could do in this case was 'take it and make one for yourself'. Finding assert library that works in both node and browser was easy. Next I created a simplified version of Vows. It is _NOT_ API compatible and it lacks large portion of the features offered in Vows (If you are developing for node.js I suggest using Vows - really!), like nested topics for example.

However for my needs I was satisfied: it supported sync and async topics (thanks Vows for the idea), the topic can be a function or any object, the tests should return its result as boolean.

A simple asynchronous test looks like this:

    vow.addTests({
        topic: function() {
          var callback = this.callback;
            next(function () {
                callback(null);
            });
        },
        'test async assert': function( shoudBeNull ) {
            return assert.isNull( shoudBeNull );
        },
        'test async assert failing': function( willBeNull ) {
            return assert.isTrue( willBeNull );
        }
    });


All topics that are functions are run and the tests are invoked asynchronously. I have also implemented this same thing in a sync manner and it was much slower, so maybe the people that dislike the 'callback spaghetti node code' are not right after all?

Example for sync test ( i.e. tests invoked directly with the topic result ):
vow.addTests({
    topic: (function() {return null;})(),
    'sync test': function(shouldBeNull) {
        return assert.isNull( shouldBeNull );
    }
)};
If you are looking for simple test running suite that works in both browser and nodejs, take a look at it. I am sure there are many improvements to be desired, but I really needed it for my use case mostly and it covers it.

The code is part of the tablet branch of the 'Tornado UI' project and can be found on GitHub.

Happy hacking.

Няма коментари: