Sunday, December 28, 2008

Effectively teaching test-first: Make it go green!

When you’re producing quality code using Test Driven Development you’re likely to use either the test first or test last approach (or more likely; a mix of those). Test first means that you write your test before you implement the method you’re testing (i.e. the functionality). If you’re following the test last mantra, you would implement the functionality first and then add test(s) to verify the behavior of the method. Strictly speaking, the latter approach will IMO not be a test driven development. If you want your tests to drive the architecture of your application, you should definitely go for the test first. It’s not that the test last won’t give you a testable application, it’s just that writing the test first makes it far easier to get your test actually be an unit test and not an integration test.

"I'm trying to free your mind, Neo. But I can only show you the door. You're the one that has to walk through it."

I must confess; I felt that writing tests first was really hard in the beginning. Before you start mastering the art of unit testing, you cannot really write the tests first unless you get some good guidance doing it. I’ve been doing TDD for a while now and I feel quite confident about it, and so I try to teach my team members the same philosophy. And the method I found that really helped getting them on the right track was to just sit down and do some pair-programming with them. We start out the session with me behind the keyboard. According to XP-ists the time between switching the roles of the driver (the one typing on the keyboard) and the observer (the one reviewing the code) should be around 30 minutes or so. But what I really find effective when it comes to teaching test first, is to do the switching after I’ve written the unit test. When writing the unit test itself, I do this while thinking out loud and discussing the code with my fellow dev. That way I practically show him/her how I think when I write the test and (s)he will have a good starting point for implementing the functionality. After I’ve finished writing the test, I just hand over the keyboard saying; “Make it go green!”

Would this method work in all circumstances? Certainly not! If (s)he was totally new to testing and I were to give an intro to unit testing, I’d probably choose another way. I’d probably show how to do some integration or unit testing on existing code before introducing the test first approach. Doing this exercise with someone who’s never seen a unit test before would probably be too much to grasp at once. When I’m coding the unit test in the Make-It-Go-Green-method I often have to use mocks to isolate the method under test and to introduce mocking to developers who have never seen unit test before will probably not be a good idea. In that case I’d rather let them do some integration tests before teaching them some real TDD. But maybe that’s just me…

1 comment:

Fossmo said...

Nice post. I have some thoughts on this. You can of course teach people to work in a TDD way, but this makes no sense if you don’t have something to “force” them into continuing to writing tests. “Everybody” say they are test-driven these days, but not many are. TDD is a mindset, a way of designing your code. It makes you think through the code you are writing before you write it. I have seen a lot of developers starting with TDD and finding it useful. But, when the deadlines are closing in they drop everything about TDD and go back to their old bad habits. So, how can you solve this? Set up a CI server and teach the whole organization about TDD and the benefits it gives everybody from manager to developer. My point is that you can’t just teach developers how to do TDD, you also need to “force” them into continue doing it and make the managers understand the benefits.