First thoughts with TDD
Bear Giles | March 30, 2011I’ve been experimenting with test driven development (TDD) for the last few evenings on a small project generating OEIS sequences for a Project Euler problem. These are extremely early impressions!
Lesson 1: Take the time to write all tests first. This was hard. You can’t just write the junit tests – you have to implement enough of the ‘real’ code for those tests to compile, run and fail. It will only take a few minutes to actually implement the function… you think. Don’t do it!
Lesson 2: You still need ‘white box’ tests. My unit tests verified behavior. Almost all were passing, just a few stragglers that could be quickly knocked out.
Nope. It turned out that several of the tests should have failed but weren’t because my objects had an internal cache that had been populated by earlier unit tests. This is counterintuitive since the interface is very much immutable but memoization is required for decent performance. That memoization meant that I wasn’t testing the code I thought I was testing and that gave me some false passes. (Note to self: add code coverage tests earlier when using TDD!)
It’s easy to solve this problem but it requires knowing that you need to reset the object or create a new one before each test. This is good practice anyway but can be a bit of a pain when you’re testing common functionality at the abstract base class level. In addition you have to know how large any pregenerated caches are. These are implementation details that you won’t know when writing the initial TDD unit tests.
Lesson 3: It’s nice to know when you’re done. It’s basic psychology – it’s a lot more satisfying to tick off the failed tests and be done than to code a bit, write unit tests for that code, then code a bit more, then write some more unit tests, ad nauseum.