Testing Will Challenge Your Conventions 16
If you are doing test-first development, you are likely to find your old coding conventions are no longer valid. There are a few changes you will need to make to your coding standards and practices.
1. Interfaces suddenly seem like a really good idea when you have to start introducing test doubles of various flavors (mocks, etc). You will find yourself creating interfaces in places where you probably would not have created them before. You’ve always known that you shouldn’t depend or derive from concrete classes, and now you are feeling the pain of non-trivial concrete classes. You are forced, more or less, to comply with the Dependency Inversion Principle. Abstraction becomes a way of life.
2. Singletons and static methods no longer seem like a great way to do work (esp in C++) because you can’t easily isolate a module that makes use of them. The exception is when a static method is totally self-contained and testable, and does not use resources like a database, file system, etc. Only the very trivial can be static. Test doubles matter that much. Suddenly substitutability is a primary measure of code goodness.
3. Private makes less sense than it used to. You can’t test anything that’s private. You need to have ways to sense that your tests are working as intended, and you have to be able to test any method that is interesting. That means less private and more accessors. Get used to living in a more public world. If you need to hide something from users, don’t include it in the interface or abstract base class. “Implements”/”public inheritance” is the new “private”.
4. You need to be able to pass a class everything it might need at construction time, so that you can pack it a stubbed logger and a faked database access module. Otherwise, you will not have the isolation you need to write good unit tests. Calling a concrete class constructor inside the body of a method now makes you cringe, because you realize you’ve missed an opportunity for abstraction, and limited the isolation of your method. The fat constructor argument list is a concession to the need for isolation and testing with mocks (and fakes, and stubs).
5. Smaller methods are the norm. It is hard to test a two-hundred line method. It’s far harder than testing a many smaller, equivalent methods. Whatever is easier to test is easier to write. Large is bad. This has always been so, since optimizers love simple functions, but now it’s real to you as well.
6. You hate inheriting code without tests, because you don’t want to reverse-engineer what the other programmer was thinking. In fact, you find yourself looking at tests before you look at code, because you know the tests are better than comments. Testing becomes a kind of “code clarity” mechanism. The profound bit is that code is more clear if it is more testable, even if you have to “pollute” the class to make it testable by moving variables and methods out of the private space or by creating interfaces, or by using fat constructor argument lists. Testability is the new legibility.
7. Hard-to-use class interfaces are now hard for you to use, not just hard for other people. You have to write the tests, so you have to use the class. Usability determines how much you will like your own code, not cleverness.
8. Performance management by old wives tales is dead. You will build for testability, and then use measurement tools to improve performance. This is what the wizened greybeards have been telling us for a lot of years, and with TDD you start listening. You stop avoiding trivial issues like copying PODS and virtual dispatches. You pay attention to more important issues. With optimization, YAGNI applies until it doesn’t, and when it doesn’t you need to know why and where.
9. You care deeply how long it takes to run the tests because you need to be able to run all of the tests all the time, after only a few lines of code are written, and after each refactoring. If it’s taking more than 20 or 30 seconds to run all your unit tests, you start looking for ways to speed it up. You must maintain test performance, because it is key to productivity.
10. Dependency hurts. You can’t afford ‘god classes’ and ‘global hubs’. If test setup becomes a chore, you immediately start reaching for the axe. You have to keep your modules isolated better than ever before. Of course, you should have done this all along, but you never felt it this keenly.
11. “Clever” is dead. Clever is hard to refactor. Clever is hard to isolate, hard to internalize, hard to phrase in tests. One point of “obvious” is worth two hundred points of “clever”.
12. Your IDE is good to the extent that it allows you to do quick write/build/test cycles. You need to do several per minute.
For the most part, TDD forces you to start doing the things you always should have done, though it signals a change in values that should be reflected in your coding standards.
Maybe you should get a highlighter and mark each section of your coding standard or architectural document that encourages any practice that in turn discourages testability. The world has changed, values have shifted, and your style guide needs to change if it is to remain relevant.

Bravo! Encore! All good points.
However, I think a more palatable alternative to the monster constructor is a lazy getter. Instead of directly instantiating a dependency inside a method, pull it out to a getter and create it lazily [if (foo==null) foo = new Foo(); return foo;]. Then you can easily inject the dependency later, if you find it necessary, by adding a setter.
If you’ll be creating many of these objects, you can use a protected factory method instead. Then, in your test, you can override the factory method to inject a fake object.
While I often use this idiom, these days, I try to use a Dependency Injection framework like Spring’s so that I eliminate the need for even this little bit of logic (which I should test drive, of course! ;) This approach also completely decouples the two classes; the “Bar” class – let’s call it – no longer knows anything about any implementers of the interface that “Foo” is implementing. Also, as concurrency is becoming more important, even something as innocuous looking as this idiom can be a source of subtle bugs if it’s not properly synchronized. (I’m reading “Java Concurrency in Practice” right now, so it’s on my mind…)
All that said, I agree that a monster constructor parameter list is a smell. Maybe “Bar” is too big? Maybe some of the parameters in the list for the constructor could be encapsulated into classes?
I think this going to become a classic post.
I’d add that the desire to set up the test with the minimum needed data means you write the code to pass the test needing only that minimum data. This really focuses your mind on the data clumps and the behaviour that is meaningful to them.
Very good points!
However, I take issue with the assertion that TDD means less private access. It may, but I often find that the need for tests to call private accessors or methods instead becomes a smell, indicating that there is a smaller class/abstraction hiding inside the larger class you are trying to test, and that you should extract this potential class and test it separately. Of course, this isn’t always true, but I think it is worth considering before “getting used to it”.
Outstanding post!!! Some people may argue some of the points (and argument is good) but overall, I’d say I’ll say you really nail it with this post. Thanks a lot.
Great post. This really puts it all together nicely.
Re public vs private. I don’t think you’re saying every “private” method should have an explicit test? Here are some reasons why IMHO this is a bad idea:
1. One definition of refactoring is making code changes that don’t break any tests – which has a strong implication that only the public interface is being tested. Exposing the “private” methods for testing can disrupt the refactoring rhythm later on as these are precisely the pieces that are most likely to get shuffled around.
2. Thinking too hard about the contract for private methods can violate YAGNI – in a lot of cases a private method might just exist to make a public method more readable. You can’t write a test for that, but dreaming up a more testable contract doesn’t really help.
3. 100% test coverage is bad! – at least as a starting position. One way to refactor code is to look at test coverage, then remove all the code that wasn’t exercised by the tests. Hunting down and testing all the private methods pretty much nukes this approach.
4. TDD-ing a single class doesn’t make sense. You’re only implementing a public method to make some other class’s test pass, right? A private method doesn’t make anyone else’s tests pass, so TDD isn’t interested in it. It’s a refactoring nicety – see point 1.
Thanks all for the encouragement and advice.
Yes, there are other ways of doing injection, including deriving testable subclasses and overriding getter methods, using a DI framework (if your language allows it), etc. But it’s all about moving ‘new’ out of the method body and out of the constructors either way. It’s even easier in Python, where you can just replace the methods and members you want to stub directly. ;-)
I certainly wouldn’t recommend hunting down private methods and writing tests for them. I’m doing test-driven development, not test-after-development. Tests come before methods (with the noted exception of “extract method”).
My feelings on coverage are here: http://blog.objectmentor.com/articles/2007/05/07/unit-tests-coverage-less-is-more
Don’t you test-drive every single class? I think it makes sense. If you don’t write them to work in isolation, why would you think they’ll work together?
Again, thank you so much for the encouragement.
Excellent post. I’ve expanded upon some of the points made on my blog post at http://stevedunns.blogspot.com/2007/07/challenging-conventions-with-test-first.html
Excellent! I found myself experiencing many of the exact same things in my coding since I adopted TDD. Good to hear this positive reinforcement that I’m “doing it right”.
Very good insights, but I do agree with Johan’s comment above re: private access.
I find that going test-driven and having a strong focus on encapsulation (which in this case means “hide as much as you can because what you hide you can change”) drives design particularly well. Usually if I want to make something public just so I can unit test it, it means that I should break it out into its own type and test that in isolation.
It’s not even that I’m thinking that you’re doing anything wrong, it’s just that I fear that some developer will read this and think “Oh, I’m doing TDD, I don’t need private methods anymore! Screw encapsulation!” and wind up doing more harm than good.
Please, think of the children!
I have just recently been doing TDD and can relate to all the 12 points here mentioned. The best thing I like about TDD is that it really does help me to “do it once and do it right”.
I like it :)
Excellent article. Thank you.
As for long parameter lists in the constructor: I’ve started putting all the object’s dependencies into accessors in a nested interface, an instance of which must be passed to the constructor. The nested interface is always named ‘Context’. Thus, if I have a class named ‘Dynamo’, all of its dependencies must be provided by a class that implements Dynamo.Context.
It’s a simple coding convention that allows me to have the benefits of dependency inversion with or without any framework. It can be used in very sophisticated ways. And pleasantly, it doesn’t make my constructor argument list grow.
Agreed—outstanding article.
However, black-box testing can only get you so far. As indicated, you should code for testability first, performance second (Knuth’s old addage brought to life). But once the thing works, and it still doesn’t perform quickly, then very often MERGING classes into one (to avoid method dispatch overheads, for example) can often give you the performance edge you need. In this case, blackbox testing is no longer adequate. Now you need “glass-box” testing (read-only access to a class’ state) to ensure state transistions remain correct even after the functionality merger.
Chip vendors implement what are known as “JTAG” interfaces, which do the same basic thing. They expose internals of the chip in a format suitable for testing. Originally designed for black-box testing the chip by setting and peeking state of the individual pins, the format has been expanded to include internal state as well. This is exploited on FPGA chips, in some cases at least, to program them live in the field, without having to burn a new program ROM.
I should point out that glass-box testing should only be used with sufficiently “low-level” stuff as to warrent it (e.g., the implementation of a doubly-linked list collection class needs to have tests that verify the list integrity after various transformations are performed on it).
This is tail wagging the dog stuff. Really, how much longer will we have to endure this cargo cult programming mentality? Fewer hammers and more common sense please.
Just one nit: “The fat constructor argument list is a concession to the need for isolation and testing with mocks (and fakes, and stubs).” It may be, but it’s also usually a sign of inappropriate layering. Fix the layers and the constructor argument list looks normal again.
Thanks for writing all this down in one place… I’m physically tired of repeating one of these every time I get a “TDD Curious George”