TDD and Complexity

The primary value of TDD

There are many positive benefits of test driven development, but for me its primary benefit is regression testing. It is about writing code in such a way that when the requirements grow we can be confident that the code we have just changed supports the old requirements as well as the new ones.

Valuable tests

Consider the following example. Let’s say we’re writing software which converts numbers to english words. We might start test driving the algorithm with the case: 0 -> ‘zero’. That’s easy enough to get passing. We just return ‘zero’. The next obvious test case is 1 -> ‘one’. How do we get this to pass? We could write something like this:

Double-entry book-keeping

The most apt analogy for TDD I have ever heard is that of double-entry book-keeping in financial accounting. Why does this practice have value? It has value because at any given time we need to know if there’s a discrepancy between the the two sides of the balance sheet. Each side contains a lot of information. Adding the numbers on each side and comparing the totals is a relatively quick process in comparison to matching up each of the appropriate debits and credits individually.

Complexity and Scope

There is a correlation between the complexity and the scope of the system under test. A single function might have a couple of paths of execution, which alone is not very many. However if that function calls another which has two or more paths, then the complexity of the higher level function increases. Some paths are mutually exclusive, but a lot of the time the paths combine.

System testing

Some have seen this solution to the shallow test problem and suggested that the ideal scope for our tests to target is the user interface, and to execute all the code in each test including framework and external components like the UI and the database.


Over the last year or so I have been using the thoughts above as a heuristic to determine, if, when and how I should be writing my tests. When I start the TDD process I follow the 3 rules. Always! But I don’t usually start test driving my code until I see a conditional or two. Even then, if those paths result in a UI interaction, I will usually prefer either manual or automated system testing over unit testing. I find mocking external systems results in tests which ultimately prove nothing, and which lead to design damage, so I like to avoid them.



Lead Software Developer and Architect in London

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Dave Hunt

Dave Hunt

Lead Software Developer and Architect in London