When having a newborn baby you read a lot of books. Books on being a parent, books on being a father, books on child behavior; books on everything you think that you need to know.
Currently I am reading ‘Why They Cry: Understanding Child Development in the First Year’ by Hetty Van De Rijt and Frank Plooij. According to the authors, all children go through a number of stages during there first year and each stage ends with a big step in the child’s physical and mental development. All children are climbing a set of stairs so to say. At the end of each stage, the child will suddenly see the world in a whole new perspective and everything that was familiar before is suddenly completely new to them. This results in the child being confused for a while and during this period, that may vary in time, he or she will be very clingy and will often be inconsolable. The authors call these periods cling-periods (translated from swedish). What’s more is that it is this new perspective on life that is needed for the child to get new insights and reach the next stage. A stage can never be skipped. The book also emphasizes that all children are climbing each step in pretty much the same time and pace. The first cling-period is reached at about five weeks of age.
How we learn TDD
When I think back on the way I started learning TDD, I realize that it went by in a similar way. At first you have only a basic idea of what TDD is all about, and you start practicing. Suddenly you learn something new that greatly improves the quality of the tests you are writing and you leap forward to the next level. You continue practicing, and soon you are ready for the next stage. At least this is how I learned TDD. I have tried to list some of the stages that I’ve reached so far when it comes to learning TDD. I might have missed some small step in between, but these are the major stages as I remember them.
Stage 1 – First step
The first stage is where you write your first unit tests. This step is probably taken on some sort of course. For me it was a two day course on eXtreme Programming. What characterizes this and probably the next few steps is that what you are doing is writing tests, as opposed to the later steps when you are probably using TDD to design and document your code. A typical test during this step would be
Stage 2 – Learning to walk
Once you start to get more of a hang on writing unit tests you now start to test in a larger scale. You might have tested some interaction between classes before, but now you start to test more advanced interaction. This stage might have been reached by the discovery of mocks. You are still not using the tests to design your code but merely for testing the code after designing it, perhaps not in written code, but at least in your head. A typical test during this step would be
Stage 3 – Coping with übermocks
One day when you are about to add some new functionality to a class you realize that the tests you wrote for that class a few days, weeks or months ago simply is too hard to modify or even understand. Typically it is a huge test class with a lot of mock-code, or it might be a class with a huge setup and only one assert. If you spot this or something similar, it is a sign that says it is time to move on to stage 3. Some people choose to focus on symptoms and not the root cause, just sighing and blaming the mock framework or something to that effect. Those people tend to get stuck at stage 2. During stage 3 you start to actually use TDD for what it’s good at; designing your code. You start to realize that a test is an excellent smell-detector. You realize that when writing unit tests starts to hurt, something is wrong. Stuff like huge set-ups and huge test classes in general, usually means that the class under test is doing too much. There might be a responsibility or two in there to extract? You start to use factories to extract object creation, and soon the huge mock-setups are a thing of the past. A typical test might be
Stage 4 – Dependency injection
Using factories, and testing every line of code, usually means that you end up with ‘factory factories’ and ‘factory factory factories’. Sooner or later you need to add some kind of dependency injection, like Spring. Now you end up with questions like ‘do i test the spring-configuration?’. Well, this is the well known debate on ‘do I test configuration’. I don’t.
Stage 5 – Testing behaviour
Now you’ve reached the stage where you add another dimension to your tests; the dimension of documentation. You start to focus on the behaviour of the class. Doing this you probably adopt a new naming convention for your tests. You probably also write a greater number of tests for your classes. A good convention is that you want to know what your class under test is capable of only by reading the test-names. A typical test during this step would be
testUsesPhonenumberToFindAddress(). Now it is not so much about test-first anymore. Now you realize that the tests and the code are one entity, tangled together, living and coevolving. It’s just as much the code driving the tests as it is the other way around.
Stage 6 – The next step
I myself has not reached stage 6 yet. I don’t know what will take me there. Maybe a cool and easy way to testdrive GUI? I yet haven’t found one, even though I’ve looked. Maybe Acceptance Test Driven Development (ATDD)? Maybe User Guide Driven Development (UGDD)? Maybe the discovery of a way to use unit tests to record history within a team, so that when all the original developers have left, NOTHING is lost.
Everyone learns in the same way?
My theory is that everyone is learning in a similar way as mine. The stages might differ some, as with babies, but maybe you recognize some things in the stages above that you have experienced on your own when learning TDD.
J.B. Rainsberger once said that a person, if i remember correctly, must write something like 1500 unit tests before he fully understands TDD. That statement would also strengthen my theory. Like there is a path that each individual must take, and there are no shortcuts. You cant skip steps in the set of stairs. You have to climb each step to reach the next.
Maybe this is why some developers whine and complain a lot about TDD. I know many developers that are stuck at stage 3. Even some stuck at stage 2. If I would write a book about my own set of stairs, maybe that could help others to climb theirs?
By the way, my daughter is approaching her first cling-period. Me and my wife better brace ourselves.