Test driven development (TDD) is one of the core practices of agile software development. When doing TDD you write an automated test before you write the productive code. More precisely, you are jumping from working on test code to working on productive code within minutes. If you are very strict about TDD, you will never touch any productive code unless a test is failing (compile errors count as failing tests). The idea of writing tests for non-existent code seems strange or even impossible at first, but it is not that hard once you have gotten used to the idea. Nevertheless, TDD is quite controversial and from my observation is only actually done by a subset of developers. The adoption of TDD was also hindered by the very absolute and uncompromising communication style of some TDD supporters. From my point of view, this debate is unnecessarily emotional. While I often use TDD, I don’t think it really matters when you write your automated tests only that you write them. While writing tests first has advantages, it can also be viable to write tests after your production code in certain situations. Let’s look at the advantages of TDD first:
- TDD makes sure that tests get written at all
- TDD prevents you from writing untestable code
- TDD encourages easy to use interfaces
- TDD helps to keep classes small
I think TDD is especially helpful for developers with little experience in writing automated tests. It forces them to write the tests first and thereby quickly exposes any untestable code. Also, it is great in projects with a lot of time pressure: When writing the productive code first, you will be tempted to skip the automated test if push comes to shove. However, if you write the tests first, there simply is no productive code which can be shipped, making it impossible to skip the tests. This is a huge advantage, especially if your managers / project leaders support the usage of TDD (at least on paper). Furthermore, when using TDD, you will quickly notice if your class becomes too big: As soon as you have the urge to test a private method directly, rather than going through a public method, you should consider extracting a new class. This new class will then contain the previously private method as a public one and thereby allow it to be tested directly.
So, if TDD is so useful, why is it not used by everybody all the time? The reason for this is simple: TDD requires you to at least have a rough idea about the structure of your code before it exists. Otherwise, you will have a hard time coming up with proper tests. Also, you will have to think about mocking/doubling any unwanted calls early. However, it is quite common in software development that you don’t know how to solve a problem when you start writing code. For example, you might be experimenting with a new API, framework or technology. In that case, you often have to write the productive code first as you can only validate that it works with the whole application running. It is pointless to write automated tests at this point, as it is quite likely that your code will change multiple times in the next hour. From my point of view, TDD is just not suitable in this case. Instead, you should get the productive code working first and then write the automated tests. However, this is not an excuse not to write tests!
All in all, I don’t believe in using TDD all the time. Developers should decide by themselves whether they write tests first or last. Being dogmatic about TDD is not helpful as it causes unnecessary resentment. Furthermore, it is misleading as TDD is not always appropriate. As long as tests are written before a fix or feature is declared as “done”, I don’t care about the exact point in time. Nevertheless, I still recommended TDD for inexperienced developers and when time is pressing.