Monday, September 27, 2010

WRU: My New Tiny Unit Test Library

The last and only developer able to let me fully appreciate the beauty of Test-Driven JavaScript Development has been @cjno, but regular "fights" with @mrgnrdrck and @sleistner have always helped me as well ;)

This post is about my tiny wru library and general thoughts about JavaScript Unit Test Frameworks.

WRU: Essentials Asynchronous Tests

The wru library is a copy and paste matter, and it is possible to test it directly here.

Why Wru

Well, sometimes I write truly small projects during my free time, and a setup that takes "zero seconds" with still a visual result of my tests could be all I need. Also for my personal projects I rarely need a massive logic behind the UT framework ... simple things are often better, but I will explain why afterwards.

Look, if you refresh, it changes!

What I have learned from Christian while I was editing his book code is that order should not matter. In my opinion there are cases where order could matter, specially when a test may depend over the setup of another one. The discussion may be long and tedious, but basically while all frameworks I know follow a for or for/in order, based on current engine implementation since for/in order has never been granted by specs, wru may have random order, and it's easy to flag it as true.

Look, it uses setTimeout and XMLHttpRequest for tests and it works!

Pretty much, wru does not give a shit about asynchronous calls but if we implement the extra file, called async.js, wru will always wait that async variable will be false before it continues.
It is true that other test could be "coolly" executed in the meanwhile, but at the end of the day the result comes when all of them have been executed ... so ... why bother? Just wait, and wru will go on by itself.

Public or Privileged Setup and Teardown

A fresh new setup per test may be worth it, that's why wru checks for these properties in the current test first, and wru itself after. If there, these are called with a temporary object shared for the test lifetime where we could store whatever we need since it's just passed by reference, as every other JS object. Handy, hu?

Compatibility?

You can try your smart phone or whatever desktop browser in this list: IE7+ ... all others. wru should simply work.

Essential Is The Key

Christian smart framework a part, 90% of Unit Test frameworks I have seen are based on following bullshit:

  • with statement, the statement everybody is scared about is far away from our production code but unbelievably trusted for all major unit test frameworks I have seen ... no comments at all ... I am simply waiting ES5 and strict tests that will nicely fuck up all your effort to write tests so far with frameworks based on the with statement

  • function destructuration, another monster able to destroy the meaning of scope and everything else that starts with the name safe environment. If your framework parses functions and methods in order to understand them, throw it away

  • any sort of magic, where magic may be good for production code and exposed API, but rarely the way to go for unit tests

  • polluted environments, via with, native prototypes and whatsoever in order to speed up those few minutes we use to write a test ... the one we suppose to trust ...

  • assertWhatever, where "Whatever" is part of the magic assertion I will never get ... and I tell you why ...



The Number One UT Framework? The Console

console.assert is probably the only thing we truly need for whatever test we would like to run in an almost clean environment, where FireBug, as example, is able to screw up a basic selector like document.getElementsByTagName("div") polluting the DOM with it's console node (a freaky and custom <firebug> node element was too clever, isn't it?)
Unfortunately, console.assert may not be available in some environment and we prefer a visual green response, isn't it? Well, with wru we can use our own style for results so that we could make the testing page as cool as possible.

Decide What To Assert

The only thing wru would assert is a truish value, and we are the only one able to make the result true ... this sounds too boring, isn't it?
The classic assertTrue is in my opinion the most ambiguous thing ever in a dynamic typed language.
All objects are true, an eqeq rather than eqeqeq could be true as well and I would like to know which one the framework is considering true.

// false by specs
console.log(
{} == true
);

// true by specs
console.log(
{valueOf:function(){return true}} == true
);

In few words, are we really sure that assertion was the one I meant? Or we have to investigate and "test the testing framework" to remember what happens behind scene?
With wru, we write the assert and if it fails, it fails. Now, tell me that you trust more the magic behind your framework ...

Stubs And Mocks Gotchas

While a stub is usually tied to a function signature, a mock is usually tied to a whole object, or environment, behavior.
What we test in this case is what we expect ... and this is ... too easy, isn't it?
We are not considering that stubbing a behavior we may have on real world so many side effects we cannot even imagine.
First of all, we are not sure that our arguments are valid 'cause we don't care about "the scene behind" our test ... and this may be good, as far as we are sure that our code works perfectly without knowing that an argument or the expected result produced by those arguments created an anomaly in the environment, and maybe an expected one.
Stubs and Mocks have been one of the "major fights" I have done with Christian during the editing, and as I have said he has been able to enlightening me about the topic ... yeah, now I got it, but stubs and mocks are still something I don't want to deal with my little projects, while surely I need them on daily basis real world tests scenarios.
For these reason, the KISS approach, I have decided to leave stubs and mocks for serious cases/applications/frameworks, but you won't find them inside wru ... but of course, we can all implement our stubs and mocks using a wru.assert(...) when it necessary during that specific test.

The Ruby World

I have heard many times Ruby community is really focused on Unit Test. Unfortunately JavaScript is not Ruby, and most of the frameworks I have seen have been created by Ruby guys that most likely did not get entirely the difference, and the beauty, of JavaScript. Please don't fall in the "common" Java developers hole, where everything should be based on new Class, you can do better!

Conclusion

I am already using wru for simple local projects and I am quite happy with its simplicity and I hope somebody will be able to "grab the concept" and create an even better framework for JS community since right now ... things are not that perfect at all.
Christian Johansen library is probably following the same simplicity, bringing much more "in the house". I suggest you to have a look but even said that, I do believe the road for a complete and standard JSUT Framework, obviously compatible with both server and client, is still unfortunately long ... well, wru is my little attempt, but yeah, I have to mock the wru DOM node in a server side environment ... but will come soon ;)

1 comment:

HB said...

Very nice. I've whipped up my own simple test framework before, not nearly as complete or useful as wru though.