Test Driven Development is something that is both old and new to me. It’s old in the sense that I’ve been writing code in a test-first fashion since I was an undergraduate CS major. Although, back then my tests were more like Console.WriteLine, to make sure something I expected to happen would happen. I always started with an expectation of what the code should do and wrote the code to fit the expectation. But those little console outputs always got deleted once I was through with them. They were useless as regression tests and they did nothing to help document the code’s behavior, let alone give me confidence to refactor later on during development.
Today, TDD is a mainstream technique. It has grown up and matured. I’m sure that what I used to do for “test first” development would be laughed at by developers in the TDD sphere today. That’s fine. But what I did then helped shape how I write code, and made it very easy for me to see the logic and usefulness of TDD. I’ve long had the mindset of expectation first, write code to meet it.
Today, TDD is an automated practice. Unit Tests are now real code that gets compiled and run, and those tests hang around for as long a the application does. They’re great regression tools, documentation, and confidence builders for refactoring. They are as important to the development of the code as the code itself.
But if you’re new to this “automated” way of testing, like I am, you may find the whole thing difficult to manage. There are serious questions that arise when you’re building a non-trival application, particularly a data-driven application. How do I test complex classes and objects that have a lot of interaction between each other? What should I mock and how do I mock properly? How do I test private methods, or should I even try? How much abstraction is necessary? Maybe most important: Am I actually testing the code properly? Am I exercising it fully?
For the past year or so I’ve been using, sporadically, NUnit as my testing framework. It’s nice, easy to use, clean code, and I dig the GUI. Seeing green and knowing my tests are passing is fun work. But even with a good test framework, and even using good design principles like Dependency Injection, making use of Interfaces and judicious use of design patterns, one eventually runs into cases where you just have to wonder if this testing business is worth the effort. Classes get complicated – not because they’re big or doing a lot of stuff (if they’re elephants then that’s probably a code smell anyway) but because they’re interacting with so many moving pieces. If you’re like me, you may find yourself sitting at your monitor able to quickly realize how you would code the solution to a particular problem, but unable to figure how you would write the tests for that solution – and write those tests first. This can lead to a lot of head scratching and doubt, wondering about the usefulness of Test Driven Development.
And even if you do manage to forge ahead and code a solution, you can feel overwhelmed at how to properly test it. Then you’re not doing TDD anyway, you’re just trying to keep your head above water and write tests after the fact.
That is the situation I’ve found myself in for quite some time. Until now. The solution to this particular problem, at least for me, has come in the form of a test coverage device called NCover.

NCover lets you know how much of your code is being tested by your unit tests. With the help of a GUI editor called NCoverExplorer, it will show you, line by line, how much of your code is being exercised by your tests. More importantly, however, it may make you rethink how you’re testing, and this can be invaluable for a newbie like me.
When I started trying TDD the hardest part was figuring out how to test complex code, especially data-driven code. It becomes really complicated when you have some class with several private methods that are manipulating a large domain object and utilizing a few injected classes and services to help. It becomes a very complex piece of code, and it can be difficult to break it down mentally into the simplest of terms. What one has to ask is, “What is really happening here, and how can I write code to exercise and test that behavior?”
You can wrack your brain silly trying to figure out if you should expose private methods for testing, or refactor your class into smaller parts, or whatever. There’s a gaggle of blogposts and articles about these sorts of subjects, and it all gets very religious very fast. For a newbie, that can make it all the more confusing, because all we really care about is: “Am I testing this correctly?” Because once we can figure out how to actually test correctly, then we can start to figure out how to test first. And that drives the design. That’s where we want to be.
The trick is learning the difference between just testing lines of code and testing a behavior. With a code coverage tool like NCover, it becomes a lot easier to start thinking in the latter form. I’m finding that the code coverage tool helps me think about things I didn’t think about before. It’s made me qestion if I’m overdesigning something (because I have to write test code to cover the solution, and maybe there’s a simpler way), or if I’m testing the behavior correctly – getting after edge scenarios and making sure misbehavior is as predictable as the desired behavior.
The biggest thing, however, is that I no longer worry so much about private methods. As some TDD gurus have said in other blogs, private methods can be tested through public interfaces. That sounds logical, but in practice it can be a bit more difficult to accomplish. Until you have code coverage, that is. When you can actually see the lines of code in the private methods being exercised, yet realize that your public methods are what you’re really testing and it is their behavior that you’re really interested in, then the process finally seems to work in a realistic fashion.
I don’t worry about private methods now – I just make sure that the code in them is being exercised completely through the public interfaces. Or more precisely – through the behavior that I am expecting the object to exhibit. Writing test cases through the public methods to exercise private methods makes me think about the behavior of the class as a whole, and what I’m really trying to accomplish. And that has made writing tests a lot easier.
And a lot more fun.