Run QUnit module setup once

How to run the async test suite setup.

Sometimes I test modules that require async setup. For example when testing a server API, I might need to login first (async request), then execute multiple async unit tests. Async module setup under QUnit or Jasmine is easy (see testing module with async setup code, but performing same setup for every unit test is:

  • time-consuming over the network
  • overwhelms remote server with test requests

I would like to run the module's setup function once, even if it returns a promise.

There are two libraries I use everyday that have once functional decorator:

allong.es has once that executes a given function and returns the result only on the first run. It returns undefined on every run after that.

var once = require('allong.es').once;
var message = once( function () { return "Hello, it's me"; });
message()
//=> "Hello, it's me"
message()
//=> undefined
message()
//=> undefined

I cannot use the allong.es' decorator, because I need to cache and return the same initialization promise from my module's setup.

lodash caches the result from the first execution and returns it on every run. It can be plugged into the QUnit tests right away:

// init() returns a promise
QUnit.module('async module setup - once', {
    setup: once(function () {
        QUnit.stop();
        init().finally(QUnit.start);
    })
});

I am using promises from Q library. Once fulfilled, the promise stays fulfilled. This allows my QUnit-compatible test framework gt to further simplify the module's async setup:

// init() returns a promise
QUnit.module('async init module only once', {
    setup: once(init)
});

Conclusion

Small functional decorators from allong.es and lodash can improve the readability of the testing code. This is especially helpful when testing async features, since the testing code avoids introducing its own complexity and clumsy syntax into the mix.