Making TDD Stick: Problems and Solutions for Adopters
I've encountered a number of teams in our organization struggling to adopt Test Driven Development (TDD) . Occasionally one or two developers succeed without help but most don't. To better understand the problem I surveyed team members and found that even after classroom training much needed to be done. This comprehensive strategy was designed to help anyone introducing TDD into an organization, though some of the problems and ideas will only be applicable to medium and large size companies.
My survey of team members (all of whom had received training) revealed these blockages:
- People find it hard to TDD on their own, when they don't have much experience with it.
- TDD Education so far has focused too much on problems that are simpler than the real world.
- More time is needed to experiment and try without the usual pressure of releasing software at a specific date.
- The average code base is full of legacy code and no training was provided in how to improve this code.
- There is never enough time to learn – there is always (artificial) pressure to ship product soon, and so we can't take the time to improve.
With all these symptoms, what are the underlying problems?
Test Driven Development can be very hard to learn. The learning phase (the time during which it becomes a deeply ingrained habit) typically lasts from two to four months, during which productivity is reduced . Eventually the benefits will be obvious and the technique is usually self-sustaining, but the question is: how to get there? Many developers give up after only a few days.
Most adoption strategies I've seen focus on classroom training (or e-learning) and one-on-one mentoring. Done well, these are excellent tools and can be part of the solution, but I think more is required.
Classroom training suffers from two key problems: the examples are too easy and don't relate to real problems; and not enough chance to practice.
Online training (both Object Mentor and Industrial Logic, among others, have offerings), has the advantage of going into more depth. However there still isn't enough chance to practice. In addition these courses are normally done without interaction with other students. Hearing questions from your classmates and colleagues can often help trigger understanding.
One-on-one mentoring doesn't scale beyond a few members of one team. This is especially difficult in large corporate environment where there are only a few experts and hundreds or thousands of people needing help.
Books are an excellent option but few developers like to read books about their trade craft, and even those who do find learning TDD this way to be a tough slog. Like the online courses, the problem is learning on one's own.
Finally: legacy code makes an already difficult problem harder. Developers rightly ask the question: "How do I test these tightly coupled objects? This code is complicated, how do I test this algorithm?"
So what works? The previous approaches suffer from two key problems: a lack of depth and no collaboration. A complete strategy will instead appeal to multiple modes of learning and have many elements.
- Classroom Training - Developers need an introduction to TDD, and classroom training is still the best one for most people. The trick is to understand that training by itself will not cause people to adopt TDD.
- Online Training - this will help entrench the basic ideas. If one step on this journey were entirely optional it would be this one.
- Patience - this will take more time than you planned.
- Measure - using code coverage tools (e.g. Emma, Cobetura, NCover, ...) and explain to team members that measurement will be one way of telling if things are getting better or worse. Obviously this doesn't measure test quality and needs to be taken with a grain of salt.
- Instill Pride - Developers need to know what clean simple code and tests look like and they need to feel it's worthwhile making the effort to produce it. Bob Martin has just written a book called "Clean Code" that answers this very call.
- Management - Developers need a clear statement from management that they understand that a transition to TDD will take time and "slow" the team down. They need to make it clear that they value quality vs. all out speed and the accumulation of technical debt. Most developers feel pressure to produce, produce, produce. Management will probably have to repeat this statement more than once. The higher up the organization this statement comes from (preferably C-level executives) the more people will listen.
- Pair Programming - if you find yourself stuck and don't know where to go next a partner can often help, even pairing with another novice can be a good start.
- Community - Create a community with your organization (or city) to share experiences. A place to network with other people who are learning to apply TDD, to learn from each others' successes and mistakes. A place to help grow the culture necessary for TDD. An opportunity to share new ideas.
- Coding Dojo – A place to practice solving a small problem together. Its a safe, collaborative environment with an emphasis on exploring a problem as a group and not necessarily solving it.
- Reading Workshops – a group of no more than eight people get together on a regular basis to discuss a chapter from a book.
- Periodic visits from a Coach - can help a team get back on track when they have fallen of the sled and stopped practicing TDD. In theses case just pairing with one or two people can help re-infect the entire team.
At the core of this plan is: creating conversations and increasing collaboration around TDD. Three of these strategies are focused in this area: Pair Programming, Coding Dojo and a Reading Workshop.
The Coding Dojo (using the Randori Format) is an event where a small group of people (max 15), solve a problem using TDD (adapted from Danilo Sato):
- The work is done on one computer with the output projected for all to see
- Coding is done in pairs
- One member of the pair switches out every 5-10 minutes (7 worked well for us).
- The coders should explain what they're doing, so the audience understand what is happening at the keyboard.
- The audience should only comment on the design when the tests run cleanly. When tests are failing they should ask questions.
- If the audience is confused the work should stop and the coders should explain what's going on.
From experience I recommend that you choose very small problems to start.
For the Reading Workshops there are a number of books that make good choices:
- on a Java Project: Lasse Koskela's Test Driven: TDD and Acceptance TDD for Java Developers;
- on a .NET Project: Kent Beck's Test Driven Development: By Example;
- as you learn more Gerard Meszaros xUnit Test Patterns: Refactoring Test Code
- and if your code wasn't developed with TDD: Michael Feathers Working Effectively with Legacy Code.
Typically teams try to cover one to two chapters a session. The pace is slow enough that people can read outside of work without it becoming a burden. In addition, it allows enough time for in-depth discussion of a few items in the chapter.
The Benefits of Learning Together
Both workshops should have pizza (or a healthier lunch option) supplied - you're asking people to spend their personal time doing something work related, they need a suitable incentive. The two workshops can alternate weeks so that people don't feel that they're getting stuck in a rut. Finally don't expect the same group members in every session.
Workshops and communities are an improvement over self-directed learning because team members are engaged in conversation and collaboration. As a result we learn about things we wouldn't otherwise have considered.
Making TDD Stick
In summary, here are the keys I've identified to create a successful adoption strategy:
- Patience, Practice, Depth
- Management Support
- Multi-pronged approach
- Developers helping developers
This approach is already in use, working to improve adoption of TDD inside one large corporation.
Thanks to Lasse Koskela, Nat Pryce, Dave Nicolette and Dave Rooney for taking the time to review drafts of this article.
 For the purposes of this article TDD is the habit of writing the tests before the code and working in small increments. It is not producing a large number of Unit tests after the code is written.
 Perceived productivity will go down - i.e. the number of stories delivered in an iteration will reduced. However since the quality will improve right from the start the slowdown isn't what it seems.
About the Author
Mark Levison is the principal consultant with Pure Agile Consulting, an Agile and Lean consulting company that focuses on helping its customers to deliver working software every two weeks. Mark has been an Agile practitioner since 2001, introducing Agile methods one practice at a time inside a small team. In the past three years, as an employee of a large ISV, he's been responsible for introducing Scrum to the organization and coaching a number of teams - including the design of a Test Driven Development strategy and introduction of a number of practices to support it. Mark is an Agile Editor at InfoQ and has written dozens of articles on Agile topics. He also publishes a blog - Notes from a Tool User. When not in front of a computer, Mark spends his time with his wife and two daughters.
This is a pretty obvious point for TDD heads, but it's difficult to explain this to non-technical folk. For example, give me a 3 month period of reduced output and hopefully in 6 months, quality & defect counts will improve. That's a leap of faith! Necessary, but a hard sell.
So it's not only the initial slowdown to get better quality but also a higher speed after few weeks.
The key however is communicating this expectation to management and team members so they don't panic when they see it happen.
Also I can tell you in a large corporate env it seemed to slow us down a bit longer. Maybe because of the crufty nature of the existing code or maybe because we'd all become old and stiff.
- FIRST, understand the reluctances and adopt the same point of view. This will give you a common understanding and baseline for discussions. In order to convince the skeptics, you need to fully understand where they stand and why they are standing there.
- Test data is a very real and complex problem. It falls in the category of things that are not addressed in "examples of using TDD are too simple and do not reflect real life problems". How to maintain test data that is relevant and exhaustive enough for tests to be meaningful and cover real life cases, while keeping maintenance/refactoring costs down? Until your team has figured this out for themselves, it's doubtful that they will "enjoy" developing automated integration tests.
- Focus on quick wins first (easy to implement, providing real benefits). Have testers and developers sit together for a while to work on designing tests first. Developers should appreciate that, hoping it will reduce the numbers of bugs found later.
- print out and distribute the most relevant chapters on TDD from Agile leaders.
- if things are not looking good -and before reluctance has built up to the point of no return!- design and agree on TDD standards for your team and *DO* impose a 3-month mandatory-no-exceptions-do-TDD period to the whole team. After this period, discuss the findings, and hopefully by then they should all be convinced (with some subtle guidance, coaching and assistance on the way!). If a justification is required in order to avoid a revolt, then show them the talk by Ken Schwaber (on Google Video, entitled "Scrum et al."). Explain to them that they have nothing to loose (this will require understanding and support from management), but everything to gain from having one more tool in their toolbox.
One point is to know the theory other is how to use those frameworks to take over the TDD.
Introducing TDD to old projects?
I do have a problem and I am looking for some advice. I am now on this project where the coding is almost "complete" but there is not a single test written for the code!! Has anyone ever implemented TDD into a project that has already been "completed"? What would be the best approach for this? What was your experience? Should we just start writing test as the bugs start coming in?
The team is not experienced at all in TDD and the project is close to deployment. My fear is that as bugs come in and being that the team is not experienced in TDD, its going to take a longer time to fix the bugs, possibly causing the client to get upset.
Any stories on this issue?
Re: Introducing TDD to old projects?
In addition helping people out of these holes is part of my business. I can be reached mark at pure agile dot com