Unit testing is a lot like exercising. Everyone knows it’s good, but very few do it or give up too early. Only those who stick with it and carry on learn to enjoy it.
I have been reading and learning a lot about testing for quite a while but in practice I always had excuses such as too little time, unit tests not being needed or worth the effort. The big ah ha came, when I realised that I don’t have to test everything and that a few tests are better than none. Another key factor that made testing a lot easier for me, is splitting and isolating business logic from ui logic. While ui logic is a pain to test, business logic is easy.
Why do I unit test?
Tests give me confidence. I know what works and what shouldn’t.
There’s nothing nicer than being 100% about something. I know my code works, because my tests tell me so.
Tests aid me in covering requirements
Requirements describe what a method should and shouldn’t do. Tests aid in applying those requirements. Writing test cases for requirements and then the function is easier than blindly writing a function that covers those requirements
Tests help me find flaws in my code
If something doesn’t work as it is supposed I create a test for it. If I have found the issue the test will fail. Also, if tests are green, than I know that the code that passes the tests is not the issue and that the issue lies somewhere else.
Unit tests are fast to create and fast to run
This is a given. If unit tests aren’t fast to run or easy to create, then you’re doing it wrong.
Tests reduce documentation effort
Each test case describes what a function can and cannot do. By looking at the test cases, it becomes clear what a function does.
Tests let me update code without worry
If I want to try anything out or test something I can do so without having to worry. If I break the code, the tests will let me know where. This also goes for changes anyone else makes without updating the tests.
Testing is fun
There’s something fun about testing the robustness of your own code. When writing tests you place yourself on the other side, as if you are playing chess against yourself. Writing tests that fail and then make them go green is rewarding.
What do I test?
Only my code
As much of my code as possible
If I can test a function and it makes sense to, then I will, bearing in mind that it must be quick and easy.
Only what I can test easily and quickly
If test case seems complex and difficult then you’re doing it wrong. Remember to only test business logic and your code.
As little DOM as possible
When do I test?
When ever I can
This is means when it’s easy to write a unit test and when I don’t have to refactor code to make it testable. If code isn’t testable but it works I leave it.
When modifying existing code
When I’m about to modify existing code that is testable I write a test or make sure there are tests. Any changes made with test coverage will highlight any breakage.
Before I write new code
This is what test driven development (tdd) is all about. First write tests, then write code. This sounds very easy, but it’s actually not until you get it. Once you get it, it’s easy.
When don’t I test?
When it’s too complicated
When writing a test seems to complicated or time consuming I stop and see if I can break up the function I want to test into smaller, simpler chunks, that I want to test.
When it’s not my code
I don’t test any code that I have not written or that has been tested already. This makes a lot of sense after reading, but it happens very quickly that you want to test code you don’t need to. Don’t test if the click event on a button fired – this goes especially if you’re using a library such as jQuery for your event bindings.
How do I test?
Divide and conquer
Split and isolate business logic from ui logic. Instead of using anonymous functions as event handlers, use named functions that can be tested.
I use QUnit
QUnit is only one of many testing frameworks. It’s lightweight and very easy to use compared to other frameworks. The QUnit cook book is very helpful and a good starting point.
A QUnit HTML page consists of
- QUnit source
- dependencies (such as jQuery)
- library source to be tested
- fixture, if needed
- test cases
Write small functions instead of one big one
Write test cases for errors