Or why they are not necessary.
Often, when you tell newbies about automated testing, the same question comes up: “And who will check the tests themselves? We'll have to write tests for tests, then tests for tests for tests ... ”Everyone loves recursion and loves her companion even more.
Strange, never came across the question: "Who is testing testers?" - in fact, the same problem is a side view.
')
But really, why there is no need to test the tests? (and testers)
To stop the imaginary recursion, tests should be perceived as part of the project, and not as an external entity.
Tests are a good example of duplication, a method of improving reliability by implementing several copies of the critical part of the system. The nuance is that, in our case, it is not the work of the resulting system that is controlled through duplication, but the accuracy of its formal model.
The following diagram should clarify the point.

When we write code (not important, tests or functionality), we build a formal model of a piece of the real world. This model, of course, differs both from the real state of things in the universe (as a result of simplification) and from the ideal result that we want to get (as a result of errors and without understanding the final goal).
At the same time, when writing tests and functionality, we look at the subject area from different angles, which leads to the appearance of two different models of the same subject area, exaggerating:
- The code of functionality describes the model of the device, in terms of its internal mechanisms.
- The test code describes the device model from the point of view of an external observer.
Thus, in the project there appear two models of the problem to be solved, created according to different principles. By comparing their behavior (through running tests), we can identify discrepancies in the models and eliminate them.
Accordingly, the tests check the code, the code checks the tests. Together it turns out a more reliable model of the problem being solved.
stone in the garden TDDTaking this opportunity, I want to throw a stone in the garden of a classic TDD, adherents of which preach fast cycles of switching between models: wrote a test, wrote functionality, repeated.
Due to the frequent change of context, it is difficult to keep in mind the whole structure of each model (especially, it's good to think about it).
Therefore, I prefer the development of long runs:
- design of a part of one model (any);
- implementation of the projected;
- designing a similar part of the second model;
- implementation of the projected;
The order (what to write first: tests or functionality) is not important - the main thing is that in the end two models are implemented. I usually start with a simpler one.
In fact, you can select not two, but three domain models:
- model in code functionality;
- model in the test code;
- model in the head of the developer.
All three models are built on different principles, which means that it can be used to determine whether a particular model has an error: if two models say A and the third B, then it is logical to assume that the third is wrong and it contains an error.
During the work on the article, no test was harmed. Thanks for attention.