writing readable & maintainable tests

Manning’s Art of Unit Testing is interesting in that it has chapters dedicated to the maintainability and readability of the tests. I didn’t read the whole book as most of it is about unit testing .NET code. (I’m a Java developer)

While these are pretty much all things I do regularly, I learned many of them through experience rather than starting out writing them that way. The most interesting along with some commentary from me were:

Readability

  • name your tests clearly – “test_method_1”, “test_method_2” are not useful names.  Better to say what is being tested.
  • use meaningful asserts – grouping your assertions into those with business meaning makes the main test easier to follow

Maintainability

  • avoid duplicate code – While this should be obvious, developers tend to be better at avoiding duplication in “real” code than “test” code.  It’s all code though.
  • avoid long and hard to understand tests – In my mind, the ideal test is as close to three lines as possible – a setup, a method call and a business assert.  There may be a few more lines.  But if there are too many, it likely the method doesn’t contain enough abstraction.
  • override toString – A great way to see the state of the object when the assert failes.
  • avoid specifying internals for dummy objects – Use stubs where you can.  Unless you are testing the interaction with an interface, you likely don’t need the granularity of mocks.

Anti-patterns

  • constrained test order – Despite the claims of TestNG, tests should remain independent of each other to make them as useful as possible.  It’s nice to see the author from the .NET world leans towards the JUnit philosophy.
  • shared state corruption – static state invites tests to rely on each other
  • multiple tests in same method vs a bunch of asserts for same scenario – I once heard a rule of thumb “one assert per test.”   I think the goal should be one scenario per test instead.  Having a bunch of asserts to check the state of a single logic thing makes sense.  Calling the same method with different parameters is crying out to be different tests.

What are your favorite tips on the topic?