Unit Testing and Test Driven Development (Lessons Learned)

13.01.2012 22:44Comments
I started a discussions with my colleagues at Tellago about Unit Testing and Test Driven Development, and a lot of interesting things came out of that discussion. Here are my thoughts.

Unit Testing

Unit testing is an automated way of testing a piece of the system in isolation (unit). This practice seems to be useful in the following scenarios:
  • When doing TDD/Test first (more on this later)
  • After a feature is complete for automatic testing of the integration of different components.
  • When documenting how to consume an API.
  • When fixing a bug, to prove that a bug exists, use the test to fix it, and prevent the bug from emerging again.
  • After coding, to avoid manual testing (something along the lines of integration testing).
  • Exploring the behavior of somebody else’s API.
Regardless of the use we give to unit testing, seems like it’s not an optional practice anymore. It’s a must-have skill that every developer should work on mastering. Here are some of the advantages:
  • You get written specifications of how the software should behave.
  • You get client code of the API under test.
  • You get instant feedback of the impact of refactorings/changes.
  • Saves a lot of time! For every time you run 1 unit test, you are saving probably 1 or more minutes of manual testing.
  • Gives you confidence for committing code.
  • Gives you confidence for touching code written by somebody else.
  • Gives you confidence for more aggressive refactorings.
There is (I believe) a downside of inefficient unit testing, and it’s that when testing the wrong things, you might end up with fragile tests, that make maintenance even harder (and more painful).

TDD/Test First

Some of us try to practice TDD or Test First as much as possible, and we strongly believe that it makes us write better and faster code by getting very early feedback of what we are doing. Here’s how ideally we would practice TDD:
  1. Define test
  2. Write test
  3. Verify the test fails.
  4. Write minimum code to make the test pass (with a minimum share of common sense).
  5. Refactor code to make it cleaner/better.
The benefits of doing test first are many, here are a few:
  • Early feedback of your code’s design. You see how your API will be consumed even before you actually coded it.
  • In order to make your test simple, the code under test should have few (or en better one!) responsibilities. This helps design your classes following the single responsibility principle.
  • Confines your brain to the smallest possible piece of your entire solution. You concentrate on doing a small part at a time, but doing it right! The good ol’ “Divide & Conquer” they taught us in the first Algorithms class.
This doesn’t seem to be that much harder than unit testing after something is coded, it actually sounds easier… WHY ISN’T EVERYBODY DOING TEST FIRST THEN??? I remember when I first read about TDD, and it felt totally unnatural (it still does sometimes). I had been coding in the entirely opposite way for so long, that it was awkward, slow, and tests weren’t as good. So here’s the catch, unfortunately, IT TAKES TIME! Not hours, or days, it may take months to start feeling comfortable with writing tests first. If somebody says that unit testing first makes them slower, to me, that sounds like they haven’t tried it enough, and they are not used to doing it. I have not known a person that has done hardcore TDD for a long time, and then came back to Non-TDD coding because they were not fast enough. PS: Thanks for the guys at Tellago for the great discussion!!!

comments powered by Disqus