Interview: Cédric Beust Discusses Designing for Testability
In this interview from QCon San Francisco 2007, Cédric Beust discusses designing and architecting for testability, problems that hinder testability, test-driven development, the "Next Generation Testing" book, performance testing recipes, and testing small, medium and large codebases.
Watch Cédric Beust discusses Designing for Testability (18 minutes).
From the interview:
[Designing for testability is] a lot harder than people think and it took me a while to realize that. The first thing that I found is a bit sad is that it's hardly ever covered even whether it's in schools or just at work or books or articles. A lot of people say it's very important to test but they don't really give you practical answers on how to do it and most of all they don't really teach you how to think, how to do it. They teach us how to write code, they teach us what Object-Oriented programming is, but they don't tell you how you write good Object-Oriented programming code, that is also easy to test and that can also be automatically tested which is another important thing. So testing is good, but automatic testing is even better, but making your code easy to test automatically is a big challenge, especially if you started writing your code without thinking about it. So in my experience it takes 4 thoughts: you need to start thinking about it at the very beginning, you need to keep testing in mind all the way through as you are writing your code and then when you're done writing you code, when it's feature complete and everything you have plenty of other things that you can think of to add to the test coverage. It's really a process that just never ends.
On Test-driven development:
I am certainly a bit turned off by all the hype and all the absolute statements that have been thrown around for the past few years about whether you should be doing TDD or not and the answer seems to be "yes" and if you don't do it there is something wrong with you and TDD is the next way of testing and everyone will be doing that eventually.
My experience is a bit different. I have tried to take a look at the way I program and I found that while I have done TDD for a certain things most of the time I don't and this kind of conflicts with everything that I'm hearing around me, so it kind of puts me in a position where I am wondering: "Am I really doing as well as I think I do or am I mistaken?" So looking back I started putting together a little list of reasons why I think TDD might be a problem or TDD might adversely impact your productivity. And I've come up with a few reasons, or at least a few justifications why I didn't do it and maybe it will make a few people who are not doing TDD and are feeling bad about it, a bit better about it.
Conclusions about TDD a bit questionable?
First, Cedric appears to assert that [paraphrased] "TDD frowns upon thinking about the 'macro-design'". Not so. TDD never explicitly prohibits nor prescribes that programmers <em>think</em> in terms of the big picture up-front - what TDD stresses is to not get too hung up on the "predicted" designs and to let the tests <em>prove</em> to you what the design <em>really</em> wants to be. Other words, go ahead and get an idea up-front, just don't spend terribly long, be flexible to it changing, and then let the red-green-clean cycle take you the rest of the way.
Second, Cedric states that "with TDD you spend a good part of your time with code that just doesn't compile and has plenty of errors in it" implying further that "TDD negates the benefits of modern IDE's". This is absolutely false. TDD allows for only <strong>one</strong> failure (compiler or assertion based) at any given time - as soon as there's a single failure, eliminate it. Further, (for many languages) its the IDE that tells me immediately of a compiler failure and gives me great tools (auto-XYZ) to easily fix it. It's the existence then of the passing unit test(s) that allows me to leverage the IDE's refactoring tools to clean up the design.
Third, Cedric then states that "TDD is great for junior programmers", implying TDD is less necessary for experienced programmers. TDD is a method of specifying behavior and thus driving design - it's a <em>cognitive</em> activity that helps drive you not only to write testable code (which it does, I agree with Cedric there), but to drive out expressive, well-factored, intention-revealing, use-driven code. I'm an experienced programmer and I find that 99 times out of 100 if I "design, code, then test", I simply don't achieve the same level of cleanliness as if I had "tested (behavior design), coded, then refactored (structure design)".
A good debate occurred between Jim Coplien and Bob Martin along the same lines as this discussion ("TDD a must or not?"), it can be viewed here.
I hope my remarks are seen as constructive, they're intended that way.