Skip to content
bebraw edited this page Apr 13, 2013 · 7 revisions

Unit Testing

TBD

Generative Testing

To paraphrase Mitt Romney, functions are objects too. This means you may attach custom properties to them. These properties in turn may be used to do some meta things. I use this approach in a library of mine, annotate.js. As you might guess from the name it provides a way to annotate your JavaScript functions with invariants. It combines the ideas of Design by Contract and Multiple Dispatch. The interesting thing is that this approach makes it possible to use Generative Testing. Just to give you an idea of what an annotated functions looks like, consider the example below:

var fib = annotate('fib', 'Calculates Fibonacci numbers')
    .on(0, 0).on(1, 1)
    .on(is.number, function(n) {
        return fib(n - 1) + fib(n - 2);
    });

As you can probably infer from the definition, this function yields a series of Fibonacci's numbers. The definition reads quite well. It also highlights some features of the library. First of all you can see the way the function is documented. It is necessary to pass the function name as not all JavaScript engines guarantee it may be introspected. After that there is a brief description and some invariants which lead to some result.

The invariants may be defined as functions and may even depend on each other. In this case I am using a helper for checking whether or not an input is a number. That way the approach may be used for simple type checking as well.

This metadata comes in very handy. I store the data into certain properties of a function generated by the annotator. Other tools may leverage this data. It is possible to generate nice documentation or tests even. It is also very easy to implement concepts such as chaining. The implementation might look a bit obscure at first. Essentially all it says is that you may construct a chain (_('foo').bar().baz().val()) based on provided functions. The function returns a function that gives you that _. After you have finished you may extract the value using "val". Note that this presumes the function result will be always passed as the first parameter to the next function so you will have to stick to this scheme for this little trick to work.

In case of testing I simply define an external invariant the function must satisfy and let my testing tool generate tests that try to invalidate that statement. It is possible to catch some very interesting bugs this way. The approach complements traditional unit testing based approach well.

You can see this sort of testing scheme in action at a library of mine, funkit. The test generator bit isn't flawless yet. It takes a while to generate the tests in the current design but not too long fortunately. Basically it seeks out values that satisfy annotate.js invariants and then uses those values to see whether or not my external invariants are true.

Browser Testing

browserling, testling, browserstack, Phantom, Casper, Zombie and such

Continuous Integration

travis (how to integrate with github project), circleci and such

Conclusion

TBD

Clone this wiki locally