Uncle Bob Says : TDD, Test Driven Development
TDD is a discipline, disciplines are arbitrary or at least they have arbitrary components to them. Disciplines have arbitrary behaviors that are driven by some substantial motives.
For example, how do doctors wash their hands before surgery? do they just go in there wash hands like normal people do? no, there is discipline something like this. There is special brush, soap and they turn on the water and it is ten strokes across the side of fingers. You understand why they do that, there is motive behind that, but is ten the right number? could it be twelve or eight, it is arbitrary. It is just a guess, ten probably enough.
The discipline is motivated by something real. The discipline of TDD works like this, There are three rules.
First, you are not allowed to write any production code until you have first written a test that fails because the production code does not exist.
Second, you are not allowed to write more of a test than it is sufficient to fail and not compiling is failing. So as soon as the test fails to compile you must stop writing it.
Third, you are not allowed to write any more production code than it is sufficient to pass currently failing test.
When you were writing code with these three laws, what you are writing are code examples for entire system. You wanna know how some object needs to be created in this system, there is test that creates that object every way it can be created. And it catches every exceptions can be caught, thrown. And these tests are not themselves a system, they are all de-coupled from each other and they have one way coupling to the system itself. They are short snippets of code that explain how one part of system works. They are the perfect kind of low level documentation for any system. You wanna know how this system works? you read the tests.
How many of you have written unit tests after the fact. How much fun is that? It is now fun, Why is it not fun? because you already know code works. You tested manually. So why are you writing those unit tests after the fact? Cause somebody told me i had to. So now you get into kind of passive and aggressive mode even if you are really conscientious. Inevitably you will come across the code is hard to test. It is hard to test because you did not design it to be testable. You were not thinking about that when you wrote the code. So now you have problems cause in order to test this function you gonna have to de-couple something or break some dependencies, re-structure the code and you look at your watch and think “Come on i know already this code works” and you walk away.
The definition of unit test, we don’t know what the work unit means, but really these tests are tests written by programmers for programmers.
We produce documents are code, full of arcane symbols in strange shapes and structure, no one else can read them only programmers. What other field, employment has problem like that? where they construct the document that are arcane and full of symbols and every symbols have to be correct. Accountants. How do accountants make sure that their documents are correct? They have a discipline that was invented 500 years ago, called Double-entry bookkeeping. They enter everything twice. TDD is Double-entry bookkeeper, is exactly the same discipline done for precisely same reason, we say everything twice, once on test side, once on production code side, they follow execution, complimentary execution pathways they wind up with zero, zero test failed. Same discipline, Same reason, Same outcome.
Do Accountants have deadlines? Do managers yell at them say we need that spreadsheet by Tuesday? Do the accountants then turn around to each other says “guys we are really under the gun the pressure’s eye, do the assets forget the liabilities. They do not, they will go to jail if they do that. This carries the weight of law with it.
Why is we can’t do this? Is there something special about software that we can ‘t do this? Are accountants more professional than we are? Are there spreadsheets more important than code we write? The code we write is many times more critical than spreadsheets.
If you decide one day that you are going to do TDD at work, you will fail spectacularly enough to convince yourself to never do TDD again. The reason for this is that the TDD is a rather significant skill. It takes months to get enough skill to bring it to work safely. What you have to do is learn the skill externally.
Q. Should every production class has corresponding unit test class?
A. You will find this, especially if you start reading books on TDD, you will see all of these examples show you one test class per production class. You don’t wanna do this. Cause when you do this, you are coupling the structure of the tests to the structure of the application code and you don’t want them coupled. You will create the fragile test problem by doing that. But you want instead, it’s for the production code to evolving one direction which is “General” and the tests to evolving another direction which is “Specific”. They will have very different shapes. The way you that if you write unit tests and you refactor the production codes then you write more unit tests, refactor the production codes and you keep this exercise going. And as you refactoring production codes you are extracting out methods and classes. You do not need to write specific unit tests for the classes you have extracted because you still are already testing them. You do not need to write specific unit tests for the functions you have extracted cause you are still already testing them. So the test code will look very different structurally from the application code and that is exactly what you want.
Things to learn more about, Mutation testing
7:07:36