Since I generally present myself as a tester, coupled with my relatively novice status when coding in Java using TDD. I don’t mind writing up my TDD mistakes here.
My basic set of mistakes
The basic set of mistakes I have made recently consists of:
- Class Names start with an upper case letter
- Doing refactoring when I don’t
- Not checking my code coverage
- Not doing a review step
- Not doing an update after a commit
So those mistakes in more detail:
Class Names start with an upper case letter
I don’t know why I kept forgetting this. Every time I created a java class I would start it with a lower case letter. For some reason I used lowerCamelCase instead of WikiCase.
Possible reasons:
- Java does not enforce this and I didn’t have a style checker installed into Eclipse.
- A constructor looks like a method and methods start with a lower case
- I do too much scripting
But, really the reasons mean nothing. We only get points for getting rid of the habit.
Doing refactoring when I don’t
The basic TDD process flow:
Failing Test -> Passing Test -> Refactor
I get full points for:
- using Eclipse to create classes by writing an instantiation line in the test and then using ctrl+1 to create a new class using the Eclipse wizard.
- writing short lines of test code and driving through to production code. (creating methods with ctrl+1 again)
- and repeating
And then I hit ‘refactor’.
I thought I refactored, but instead I ‘rewrote’. I introduced new lines of code which I did not drive with tests and which the original tests did not cover. And I introduced new bugs as a result - even though the old tests passed.
I did not refactor, and those new lines of code should have meant new tests.
Not checking my code coverage
I wrote a whole bunch of code with a whole bunch of tests and then when I eventually ran code coverage I didn’t get 100% - hey, what gives.
Some of the additional lines of code resulted from my rewrite ‘refactoring’. And some of it because I had test driven my code with higher level acceptance tests, and then forgotten to drop down to TDD my class level code.
By reading the results of my code coverage I could spot tests that I had missed out. Which I would not have done, had I done TDD better.
Not doing a review step
TDD demands intense focus (at least it does for me) and at the end of a session when I have my code and my tests pass and I’ve ‘really’ refactored. I find it so tempting to just hit the ‘done’ button.
And I did.
But I shouldn’t.
I should have reviewed. I should have stepped back and gone ok, so I’ve met the acceptance criteria, but maybe I need some unit tests.
- What exception conditions might I encounter?
- Why did I not handle nulls as parameters?
- Why did I not think about those special cases?
As a tester, I think about those things when I review stories. Exactly those kind of things. I did not manage to swap well between test and developer modes when learning TDD.
Not doing an update after a commit
A killer mistake if you work in a team environment. Stick your code into the repository but then not get the changes that other people have made.
My Excuse? I do most of my coding at home on my own so I don’t normally have to do this step.
I got lucky lucky lucky. I wasn’t pairing at the time, but my pair spotted it during our next pairing session.
Mistake Tracking
I made some TDD mistakes. So to fix them. I tracked them.
I tracked the mistakes by creating an index card that listed the ‘bad’ things on one side, and the ‘good’ things on the other side. Then noted when I did the bad things, and when I did the good things. The writing of these statements seems important. So if we have a look at the card…
I write the ‘bad’ things in the leftmost Column “Replace”.
And the ‘good’ things in the rightmost column title “With”.
The act of marking when you do them becomes so annoying and embarrassing that you really do build the motivation to stop.
Those that particularly annoyed me I put a big X against or started using a bigger pen.
The hardest part of this process becomes maintaining the discipline to mark down when you did or did not do something as this type of reflective behaviour takes practice to build up.
By taking notes of what I did ‘wrong’, and ‘right’. I feel that I have managed to build up a reflective style of working. And I do feel that this has also had a good knock on effect on my exploratory testing note taking.
But note the important points about the “With” column phrasing:
- write the behaviour with a positive intent
- write the context of the behaviour (when? after what?)
By, write behaviour with a positive intent I mean phrase it in terms of what you want to do, instead of what you don’t so instead of “Stop committing without an update” write “Do an update after each commit”.
When I think I finally got it, I added a … in the with column. If I make the mistake again then I’ll start a new card with the old behaviours and the new behaviours, and I’ll date the old card.
The list of positive behaviours:
- Create ClassNames with UpperCase First Letter
- Refactor Automatically
- Drive Manual code changes with tests
- Check Code coverage After Refactor
- Review code and Add Additional Unit Tests After Refactor
- Do an Update After Each commit