I originally posted this on my blog almost two years ago. If it's interesting to you, I post new content on daedtech.com roughly weekly.
Today's question is about test driven development. Specifically, it's about test driven development when you're trying to get a team to do it -- a remote team. Here's the question (directed at me some time ago on Twitter).
I've talked so much lately about consulting and other such topics, that it's fun to get back to programming a little, if only for nostalgia's sake. So, yeah! Let's talk TDD.
I have a lot of coaching experience, a lot of consulting experience, and a lot of TDD experience. I'm going to combine all of those things into a series of suggestions. This is what I would do if a prospective client wheeled a dump truck full of money up to my place and asked me to do what you're doing.
First: Test Driven Development Evangelism
Leadership is on board, and you're on board. That's important. But without the team on board, it won't matter at all. With a new initiative like that, lack of team buy-in means they'll humor you until the first excuse to stop comes along.
Now, getting buy-in doesn't mean that you necessarily make everyone true believers. A lot of times, the easiest way to convince skeptics is to (accurately) point out that having TDD on their resumes makes them more marketable. So, hey, look at it as that your company is paying you to learn a skill that makes you worth more.
Even better than that, though, is to combine that with promise of alleviated pain.
Find some big snarl of global state and complex methods, and point out that TDD is like kryptonite for that kind of thing. Or demonstrate the embarrassing-defect-saving power of a regression test suite and then ask if it wouldn't be nice to have that everywhere. Whatever the magic selling point is, try to find it.
And, by the way, this isn't specific to remote test driven development. You should apply this to any effort to install TDD (or really any practice, frankly).
Do Your Homework to Make Things Easy for Them
Alright, let's assume you've done a good sales job, and everyone is chomping at the bit for TDD. Or, at least they're not chomping at the bit to fight you every step of the way. That's a good start, but there's more to do before you ever go onsite. Oh, and you'll need to go onsite. But I'll get to that in a minute.
The next thing you want to do is to make sure that they have as soft a landing as possible. And you can do this by ensuring that they have all sorts of examples to refer to as they start their journey. So go into your shared codebase, and create those examples for them in the code. But don't stop at creating the code itself. I suggest that you create code-casts where you demonstrate TDD in your codebase.
Demonstrate a variety of things, such as:
- TDD with a brand new class.
- How to test drive when you're making a small modification to a simple class.
- Test driving a class with injected dependencies (i.e. mocking).
- TDD in hairier situations.
- When to retreat and live to fight another day.
I can't stress that last one enough, frankly. In my book on unit testing, one of the points I emphasize is to recognize that some hills aren't worth dying on. People early in the TDD journey should make strategic retreats from particularly nasty legacy methods until they up-skill.
Schedule an Onsite 3-5 Day Workshop
Now you've done your homework, and you're ready to kick off the project. Don't do this with a laggy webex and a power point.
Fly yourself out to wherever the team is (or fly them all into some central location, if they're all distributed). This shows everyone that you and leadership are serious and willing to invest in the team.
But it's also effective to get things going and to build momentum. TDD is actually really easy in initial workshops.
You get the group together in a conference room, set the rules for Randori TDD, and everyone goes to town on a green field calculator or Uncle Bob's bowling score kata thing. When there aren't any 4,000 line methods, global variables, hard-coded logger calls, and whatnot, TDD is actually pretty straightforward.
So start with that and build on small wins. Spend the first day or two hammering home the mechanics of red-green-refactor in a way that builds team confidence. Then move on to your team's actual codebase. Pick some relatively easy places to start, and start there, adding some hypothetical functionality to your actual codebase. (You'll probably discard this.)
And, finally, on the last day, move to advanced scenarios.
Hopefully the team starts to grok some of these, like mocking, characterization tests, and the like. But the real goal here on the last day is to show them when to retreat. Some may disagree with me on this, but nothing kills the will to test drive faster than banging your head against some insane mocking scenario for 2 days instead of writing useful code.
Clear Your Schedule And Setup Open Office Hours
After an intense week of pizza, group activities, and collective positive feels, everyone will fly home. Or you'll fly home. Or whatever.
This is the easiest time for the momentum to disappear. So leave the team with a promise: that you'll be available anytime they hit a dicey scenario. Promise them that, and then make it true.
Assume that you're going to spend a few weeks doing a lot of remote pairing with them, helping them get unstuck. Set aside office hours where they can simply call in and ask for help. Beyond that, make yourself open to them scheduling appointments.
When you're not busy, keep your eye on the codebase and the commits. Do you see people struggling? Reach out to them. Are people not committing any code at all? Reach out to them. For some period of time after the initial kickoff, you need to make your job "TDD Champion."
Create a Testing Roadmap and Declare War on Legacy Code
So far, the team is probably enlisting your help to test drive new features and bug fixes. And that's a great start. But sooner or later, you're going to need to take the fight to the God classes and singletons and whatnot.
I've actually done this in automated fashion as part of my codebases assessment practice, but you can do it manually. Go through your codebase, class by class if needed, and rank things from most to least testable. Sprinkle getting legacy code under test into your team's normal workflow, giving them increasingly challenging bits of legacy code.
This serves two purposes:
- The obvious one of getting more code under test.
- The subtler but equally important one of giving them fewer and fewer excuses to punt on TDD.
Remember that I said you should allow newbies to punt on TDD at times, so as not to get discouraged? I stand by that. But letting them punt forever is pointless. So you have to create subtle but firm pressure to keep raising the bar.
Create Group Incentives
When you're colocated with the team, you can rely on group dynamics to a certain extent. You can also walk around and say, "so, 'sup with the TDD?" You can try these things with a remote team, but the effect isn't going to be the same, I promise.
So you need to think more in terms of explicit incentives and less in terms of group dynamics. Find ways to reward the team for collective, real progress.
When I say real progress, I'm referring specifically to not using (easily gamed) code coverage as a measure of progress. You're going to have to be more rigorous and creative. It's a tall ask, but then again, so is installing a brand new development methodology remotely.
The right set of incentives creates a feeling of mastery and progress, while inspiring the group to hold itself collectively accountable. Gamification will take you only so far. You and leadership should put some actual skin in the game in some form or another as well.
Don't Count Backsliding as Failure -- Just Try Again
I'll say it again. Installing a new development technique remotely with an unfamiliar team is no small feat. No matter how much momentum and enthusiasm you start with, you're going to hit lulls and you're going to backslide at times.
With TDD, it usually comes the first time a deadline looms. Everyone says, "ugh, we don't have time for this -- we'll totally start again once this patch goes out."
You can (and should) fight this on both the front of expectations management and sticking to the process. But you're going to lose this fight at some point or another. When you do, remember that you've lost a battle -- not the war.
I say this because driving an adoption like this is a long game, and it's exhausting for its champion. It's going to take a lot of your time, it's going to be frequently thankless, and you're going to hit all manner of setbacks.
You have to push through all of those, stay positive, and keep plodding along. You'll get there.
If you'd like to ask a reader question, you can do so at the "ask me" page.