Steve Berczuk: Are there some contexts where TDD doesn't make sense?
Dan Wellman: Recently, we've started working with new startups (as opposed to enterprises or "established" startups), and we sometimes think differently about which practices we use and how we apply them. This is a subject of vigorous and healthy debate at our company. For example, if a new startup has six weeks to prove itself as a worthy investment to funders, a rigorous suite of tests and a highly flexible design might not be the most important use of developer time and money. Sometimes that means not writing tests at all. Sometimes that means dialing back the scope of the tests—for example, writing high-level acceptance tests but not writing as many unit tests, or vice-versa.
Steve Berczuk: What are the prerequisites to a team’s starting to use TDD?
Dan Wellman: I'd say interest, motivation, some knowledge about how TDD works, and some slack to try, fail, and learn. TDD, like any new skill, takes some time to practice and learn. And, I'd say after several years of practicing TDD that I'm still learning! Generally, that means it takes longer for a feature to go from "started coding" to "finished coding," though typically those features have fewer programmer mistakes in them as opposed to features implemented without any tests at all.
Steve Berczuk: Are there domains or aspects of a project where TDD makes more or less sense?
Dan Wellman: When I'm not sure how to design or implement a feature, I start an experiment without worrying about tests and with the aim of getting some fast feedback: "Is this even possible?" "What happens when I try this?" Once I’ve settled on what the design would look like, I revert the code and start applying the TDD process from scratch.
I don't typically test drive UI layout or look-and-feel changes. I may test that certain elements are present (e.g., "If I've got the editing permission, I should see the save button"), but I tend to find more value in testing the application’s behavior and business logic.
Steve Berczuk: What are the major technical challenges to adopting TDD?
Dan Wellman: Many teams start trying to practice TDD on an existing project that was built without any automated tests. That seems to me to be one of the hardest tasks for a programer to do. It means learning TDD and trying to apply it in a codebase that might be hard to test. In those cases, I've seen it pay off to be persistent and creative. And, reading Michael Feathers' Working Effectively with Legacy Code helped me immensely when I stared doing this. If you want to start practicing TDD and you're swimming in a legacy code base, I can't recommend this book highly enough.
Another challenge is if the project interacts with a third-party framework or API that is hard to test. What I've seen work in those cases is introducing an adapter layer that separates the core application's code from the third-party code. Alistair Cockburn describes a design pattern that uses this technique called the “ports and adapters” style. Steve Freeman and Nat Pryce describe how to build a system using this technique in their book Growing Object-Oriented Software, Guided by Tests.