(Testing with) less is more 07 Dec 2011
I had my first real experience with unit testing in my software engineering course as a freshman. In this course we challenged our freshly developed skills in Java programming. Do our programs as we have told them?
We did our tests with JUnit, a pretty nice testing framework for the java vm.
Lately, I’m experiencing with node.js. Back in the Java world, I was left with one, maybe two options on how to test my programs. In JavaScript I have an numerous amount of testing frameworks at hands. All try to achieve the same thing, but slightly different.
Well in the tradition of xkdc I will present my own unit testing framework
Well… No.
While thinking which framework suits my testing best I discovered that the only required part of testing is an integral part of node: assert
Let’s try to test without an framework.
Yeah sure, but sometimes I need my friends setUp
and tearDown
No need for a framework, the only think required is a file liked this
module.exports =
setUp: () -> hereIReturnAnObjectWithAllRequiredMethodsMyTestNeeds
tearDown: () -> thisObjectIsOfCourseReusableAboutAllTests
And what about the structure of my tests? I don’t want one big file with a long lists of assertions. What about using the things we have: directories and files. Each test is in own file. This makes not only the tests small in size (and thus more readable). You can also put the description directly in the filename. Another advantage is that you can cherry pick the tests you want to execute (perhaps you have some lengthy integration tests and only want to test an part of the application).
How should I test asynchronous code?
With the above tools it wouldn’t be possible to detect the defect in this code:
storesValue = (value) -> (next) -> # upps comment instead of this: next value
If javascript has to code to run it will end the process.
storeValue(5) (result) -> assert result, 5, 'wrong result returned'
In this code the callback would never be executed, and the assertion couldn’t be triggered.
So we need an mechanism to verify that a specific part of our code has been executed before we put our process to an end.
Why not extract test.done
from all the big asynchronous frameworks and
modify our test a bit
done = require('done')()
storeValue(5) (result) ->
assert result, 5, 'wrong result returned'
done()
And this method can be built in 4 lines of code (trust me).
Advantages
- less code, less bugs
- no external dependency for testing
- not another syntax for a unit testing framework to learn
- you can execute your tests with a basic
node test/*
Disadvantages
- you need to find the unicode character for ✔ yourself
- no test runner that exports xml :(
So I would invite all fellow coders to rethink our development process. Do we really need all the big tools and frameworks we use everyday or are we just pulling all the junits of the world around up to now, because we did need them long ago and got used to them?