A few weeks ago, I iterated characteristics for a very-first exercise for TDD newbies. But once you’ve settled on a great introductory TDD example, how do you deliver it? What do you talk about or demonstrate, and what do the students do on their own?
I used to initiate TDD training by first doing a demo, then letting students do their own similar exercise (or even the same one) on their own. When demonstrating my example, I’d first talk about the TDD cycle, then launch into some coding. During the demo, I’d discuss the mechanics of their unit-testing tool and assertion framework of choice, what a test looked like, what sorts of things to focus on during refactoring, and so on.
I got good at coding while talking and looking at the students. So what? The problem was, I was blathering and they were watching, providing a great opportunity for them to start tuning out–a very bad thing for people who likely are anxious about TDD in the first place. I tried a bit of choreographing: I’d demo bit-by-bit, waiting for students to catch up on coding the same bit. It worked, but still seemed like too much was getting covered all at once.
My goal instead became to get students into their own, simplest possible exercise as quickly as possible. Using a technique I learned from James Grenning long ago, students are given a complete set of tests for the first exercise. Initially the tests are all disabled or commented out. The tests are ordered to best promote consistent incremental growth of the solution.
The student’s job is to uncomment one test at a time, watch it fail, get it to pass, refactor, and then move on to the next test. My primary instruction to them is to ensure that they write no more code than needed to get the current test to pass. This is a hard and important lesson to learn and understand! My secondary instruction is to tell them to clean the code up with each passing test (yet they never do enough of it, regardless of instruction!).
If I’ve done my job particularly well in terms of ordering the tests, I can even introduce a tool that forces the issue of minimal implementations: The TDD Smackdown Tool is a simple test runner that generates test failure when students write code that causes any of the still-commented-out tests to pass. It’s not foolproof, but might prevent them from coding too much before you have time to get to their machine to, well, smack ’em down.
By simply following the instructions and getting tests to pass, students learn a lot by osmosis. A second exercise, without the training wheels of already-written tests, goes far more smoothly. They can look at the first exercise for what a unit test must look like.
No technique is perfect. Some possible challenges / discussions:
– “Since I have all the tests, I know what the complete solution will require, so why not code it already?”
– “Would I normally write all the tests at once?”
Using this Grenning Method, the focus shifts to one core element: how to incrementally grow a solution using TDD. Discussions can focus on the red-green-refactor cycle, emphasizing refactoring and “red first” / minimal implementation.