Mythbusters: Unit-testing

Originally published on blog.einbu.no July 5. 2009

While I believe most or many developers have heard of JUnit/NUnit/<your testing framework here>, fewer know how to write a test and running it using such a framework. And from those, even fewer have a good understanding of how to make unit testing a part of the development workflow.

I've known about unit testing and unit test frameworks for maybe 7-8 years. I first tried using it in a small project 5-6 years ago, but it is only in the last few years that I've learned how to do it right. (ie. found a way that works for me and my team…)

For me some of the things learned were:

  • How to test what. (Like how to test logging in or accessing files. How to abstract yourself from the database. How to do mocking and use a mocking framework. Learn techniques and patterns that increase testability.)
  • Integrating unit tests in my IDE, and having shortcuts to run/debug tests.
  • Having some tests is better than no tests at all.
  • More tests can be written later when a bug is discovered. Write the test that proves the bug, then fix the bug.
  • Differentiate between unit tests and other tests like integration tests.
  • You need to practice to get good at it.
I found a question titled: Why is code quality not popular? on Stackoverflow yesterday. Several people had listed reasons for not doing unit testing. There were a lot of misconceptions there. Here are the main reasons mentioned against unit testing (the myths) with my response:
  1. “Its dull to write tests.”

    Well, I certainly don't think so (anymore): I get a sense of accomplishment of seeing the green bar indicating all OK. I guess this comes after you've seen the (green?) light! ;-).
  2. “There's no time to write tests.”

    Proponents of unit testing will show how unit testing in the long run saves time. If this is true, then we shouldn't skip this testing thing that saves time…
  3. “Laziness…”

    Ok, agree… Why do if you don't have to… See point 4 and 5.
  4. “Management won't let us.”/”Ignorant management.”

    Management has to buy into the idea of testing. Pointy Haired Bosses are no good here… (This is probably the only point on this list that holds true as a point against unit testing…)
  5. “More work, but no rewards.”

    Again, see point 4. At the very least, if it is defined as part of our job, “rewards” may include a pat on the back, a price, a bonus or even just getting to keep your job. (ouch!) The other kind of reward is that the code is easier to maintain. Having tests help you confirm that fixing one thing doesn't break some other thing. This is a long term reward.
  6. “The code will change, so the tests will fail in the (near) future.”

    When code changes in a way so that the tests are incorrect, (ie. the requirements change) then it is OK to change the tests to align with the requirements.
  7. “The test we wrote some time ago (probably) don't work anymore.”

    Then you're doing it wrong. Everyone on the team must learn (and agree to) always run the test. Maybe many times a day. If requirements change, see point 6.
  8. “Project is not important enough to warrant tests.”

    Why bother doing the project at all? We're already skipping unit tests because they're not important enough… Surely some other more important project needs the resources. Or… Maybe not, but its a good learning experience to write the unit tests. And you're ready when it becomes important enough. If you already are really into unit testing then writing the tests comes naturally, and the cost is minimal.
  9. “Unit testing is also weak at finding problems that haven't been considered.”

    True, but that is not the job of a unit test. Its job is to verify that the expectations you have on your code still are true after changing the code. (See also point 10)
  10. “It takes too much time and effort to think of all possible cases and write all those tests.”

    You don't need to. Just start by writing some tests and move on. (Typically test for edge conditions, both in and out of range, valid and invalid arguments in.) If you later find you should've tested for yet another condition you didn't think of (because of a newly discovered problem?), write the test then.
  11. “Methods not being easily testable” (due to database interaction or other external resources.)

    If its not easily testable, maybe the code isn't written right. Maybe it should be broken down to smaller problems. You might need to use mock objects to simulate the external resource. When you don't want your unit tests touching that external resource, this is where other test types, like integration tests, come in to play.
  12. “Not feasible for big projects”

    Maybe not as an afterthought, no… But write test for those things you're about to fix/change/add. For every test that gets in there, you'll have a better test suite. It won't be complete, but “some” is better than “none”. Doing it from the start should be little effort, even on a big project.
  13. “No testing framework exists for the my platform.” (embeded device etc.)

    Unit tests can exist outside a framework.
    • Write a program that tests your program.
    • Write a “self-test” method.
    • Build hardware to test your embeded device software.
Though it may not always be either practical or sensible to do so, there is a way...