Writing Testable Code

A common problem that most beginners in the TDD world have is how to define a unit test. Although seems like a (very) simple task – writing a good unit test is not that simple.

That’s why when I saw this post (On Google Testing blog) I knew I found something worthwhile.

In the post titled “Guide: Writing Testable Code”, the author explains how to write your code in such a way that writing unit tests for it would be trivial and easy.

The reason that writing simple short tests is not easy is because the code that is being tested wasn’t written with testability in mind.

The author defines ten simple rules (I’ve changed the titles a bit):

  1. Don’t mix object graph construction with application logic.
  2. Use dependency Injection to get object dependencies.
  3. Don’t do too much work in your constructor.
  4. Global State is bad for you.
  5. Singletons are just as bad.
  6. Static methods: (or living in a procedural world).
  7. Favor composition over inheritance.
  8. Favor polymorphism over conditionals.
  9. Mixing Service Objects with Value Objects.
  10. Mixing of Concerns.

By following the rules above you can create testable code that make it easy writing simple short unit tests.

Although testable code is a must I think the post assumes that the reader is already aware of the other most common error – Trying to test too much on single test.

Last week a Typemock user complained that he was having problems testing asynchronous method calls.

Basically what he tried to do in his test is to run function “A” that call a delegate B and test the results of a parameter passed to B. What he could have done instead is to write two different tests – one would test the function not including the call to the delegate and the other to test the delegate functionality.

 

It is easy to forget that unit testing are simple short tests and should never be used to test a full execution of an application. We got integration/acceptance tests for that purpose. And so sometimes when developer claim that their tests break way too often it is due to the fact that they are trying to test too much instead of just a specified feature.

 

One solution for this problem is to define the following before writing a test:

  • Tested functionality.
  • The Scenario we’re going to run.
  • Expected result.

 

And so these three points help us create simple and well defined tests.

Tags: