Test-driven development (also test-driven programming; Test first development or test-driven development (TDD) is a method that is often used in the agile development of computer programs. In test-driven development, the programmer consistently creates software tests before the components to be tested.
According to the classic approach, for example according to the waterfall or the V-model, tests are developed in parallel with and independently of the system to be tested, or even after it. This often leads to the fact that the code is difficult to test, and thus the effort required for the tests is high and they do not achieve the desired or required test coverage. Possible reasons for this include:
- Lack or lack of testability of the system (monolithic, use of third-party components, …).
- Prohibition of investment in non-functional parts of the program by the company’s management. (“Work that you don’t see later in the program is wasted.”)
- Creation of tests under time pressure or purely to achieve the desired test coverage.
- Negligence and lack of discipline on the part of programmers in test creation.
- Focus on the white-box test on the system to be tested and its peculiarities and the resulting “around errors” testing.
- The method of test-driven development tries to counteract these disadvantages of white-box tests and also to get a software design that is better adapted to the task of the software and more maintainable.
When using test-driven development, an average of 45 percent of all errors can be detected or avoided. In comparison, only 30 percent of errors are detected on average when unit tests are used alone.
---

Criticism of Test-Driven Development
The main objection to test-driven development is the supposedly high effort. However, the idea described takes advantage of the fact that the mental effort that is invested in the constructive description, i.e. the program, during programming, and makes up the majority of the programming time (in relation to the typing effort, for example), includes a list of individual points and cases to be fulfilled. With just a little more effort, the case to be covered can be described exactly at this point in time before programming and writing a few test lines beforehand can even lead to better mental structuring and higher code quality. Second, test-driven development leads to a certain discipline of which functions are implemented in which order, because you first have to think about a test case, and thus potentially to a higher consideration of customer benefits, see also YAGNI.
Unit tests or automated tests in general are often described as the safety net of a program for necessary changes, without a high level of test coverage, a software system is generally more susceptible to errors and problems in further development and maintenance.
Even at the first creation, with a little practice to fulfill a certain functionality, the effort with TDD can be less than the effort of a supposedly fast solution without automated tests. According to the consensus view, this is all the more true the longer the system is durable and thus subject to repeated changes. The effort required to write automated tests afterwards is much higher, because the individual requirements and program lines have to be mentally analyzed again, and a comparable test coverage as with TDD is then hardly realistic for reasons of effort and cost alone.
The method of test-driven development can also be used incorrectly and then fail. For programmers who have no experience in this, it sometimes seems difficult or even impossible. You’re wondering how to test something that doesn’t even exist yet. The consequence can be that they neglect the principles of this method, which can result in difficulties in the development process or even its collapse, especially in agile methods such as extreme programming. Without sufficient unit testing, sufficient test coverage for refactoring and the desired quality will not be achieved. This can be counteracted with pair programming and training.
A major argument of opponents of test-driven development is that unit tests in particular unnecessarily increase the effort involved in changes to existing functionality, because a change to the production code causes a disproportionate number of unit tests to fail. However, the reason for this is usually that the tested unit has not been sufficiently separated, i.e. the tests are not atomic.
To avoid this problem, it is necessary that programmers are trained on how to break down the requirements into atomic functional units and practice doing so.