Test-driven development based on the Munich school

Test Driven Development (TDD) is a popular and useful methodology. If used correctly, TDD significantly reduces the defect density without having to accept a loss of productivity. Most importantly, TDD helps improve software design.

TDD rediscoverer Kent Beck reveals that he took the idea from an extremely old programming manual. In fact, the origins can be traced back to John von Neumann in 1957, who operated TDD at the time with pre-cut punched tapes.

In many projects of the 1960s and 1970s, including at NASA, there are references to early TDD. Unfortunately, the knowledge about the technology has been forgotten for a long time or was only known to a few initiated. It was not until 1989 that Kent Beck developed sUnit for Smalltalk and later jUnit for Java, thus establishing the modern TDD. More than 60 years of TDD are reason enough to ask how the methodology has developed since then.

If you look over the shoulder of TDD developers, you will quickly recognize different methods. Various styles have emerged over the years that the scene likes to refer to as TDD schools. In fact, parallels to martial arts can be identified – schools there often bear the name of their regional origin. The same applies to test-driven development.

At least six schools can currently be identified:

There are other TDD styles as well, but the six stand out because they have their own name and their respective concepts are well documented. Chicago and London are the two oldest and there is plenty of literature available for them. The other schools are so far underrepresented. That is one reason to present the Munich School in more detail in this article.

David Völkel started the Munich school primarily as a reaction to the London school. The latter records the so-called outside-in procedure as one of the outstanding properties: an acceptance test maps a required requirement at a high level. A lot of effort is required to make it pass (green). This is served by further test-driven development from the outer API to the core of the production code. The first acceptance test remains red.

Only after the end of the inner TDD cycle does the outer acceptance test turn green, and a new cycle begins. Emily Bache describes this procedure as a double-loop ATDD (Acceptance Test Driven Development).

The Double Loop ATDD extends the classic TDD cycle with an external acceptance test-driven cycle.

The specific requirement is always in the foreground, even with the inner loop. The procedure creates a layer structure in which each new layer fulfills the requirements of the one above it. According to the YAGNI principle (“You Aren’t Gonna Need It”), this prevents unnecessary code from being created. Every piece of production code is proven to be required in the end for the project. Verification with mocks or spies takes place through the back door, so to speak – the so-called backdoor verification, so that the tests do not remain red for the entire time of the inner loop.

pushSpy = jest.spyOn(Array.prototype.push);
deck.addCardOnTop("9-Hearts");
expect(pushSpy).toHaveBeenCalledWith("9-Hearts");

The examples in this article are written in JavaScript, but the programming language is irrelevant to the TDD schools and related concepts.

In the code specifies the method addCardOnTop the “9-Hearts” card on a deck of cards. Instead of checking the changed state (“9-Hearts” on top, one card more than before in the deck), backdoor verification ensures that the production code uses the underlying method push of the array object with the correct parameter "9-Hearts" has called. In this way, a layer of production code can be written without the underlying layer having to be present.

So on the plus side of the London School is the provability that the production code is required. So nobody writes superfluous code. Another advantage is the consistent approach: it is usually clear which step is next. Free experimentation as in the Chicago School is not necessary.

On the other hand, the frequent use of mocks is a disadvantage. They are often difficult to read and lead to a strong interlocking of test and production code. The result is fragile tests.

Compensating for these weaknesses was the motivation behind founding the Munich School. It tries to answer the question of whether the outside-in approach with all its positive properties can be retained without having to resort to mocks.

The Munich School is not a completely new concept, but takes up existing patterns and concepts that have been known for a long time and that they bundle together into a coherent approach. The following concepts serve as the basis:

There are also two more that Völkel has developed to enable his approach: Backward Calculation and Intermediate Test.

Previous post A step into the future: TailwindCSS presents just-in-time compilers
Next post Visual Studio Code, Part 3: Implementing Your Own Extensions