Test-Driven Development
I’ve been writing unit tests for quite a while now (this practice seem quite common all over now). In addition, I’ve been very interested in TDD over the last couple of years. This month I wanted to get a step further, so TDD has been my main focus (see my post “Apply the knowledge”). This extra attention on TDD has given me some new and exiting insites to how and why, so here’s my new found thoughts, together with my general view on TDD.
Design is the key
I feel stronger and stronger that TDD is all about design, especially if you take the need-driven/mockist-approach (see article reference below). Your system will look different if you create it test first. Apart from the fact that it will be easy to test (never running into detestable objects), TDD-developed systems tend to have lower coupling, which in turn has a positive effect on a systems flexibility, which again is nessecary for applying refactoring.. I could go on.
The article, “Mock roles, not objects”, describes TDD as a design prosess in an exellent way. When I first read it, it really opened my eyes on how to design flexible systems with TDD.
Verification
In his article “Mocks aren’t stubs”, Martin Fowler writes about the difference in using mock objects or not. He finds that (among other things) when using mocks you use behavior verification, while others use state verification.
Fowler argues also that mockist tests couples the tests to implementation since it uses behavior verification. Allthough I do not totally agree on his views on this issue, here he has a good point. The main problem with behavior verification is that the test and the SUT (Subject under test) is tightly coupled together. Coupling between testclass and SUT is no problem when they are coupled together on the expected external behaviour, because if you want to change that, you want to change the test first. But it is a problem if a change that does not change the external contract, will break tests. This means our code is less flexible, and it will lead to more work for every internal change, like a refactoring.
This does not mean that I’m giving up mocking (I still love the way it drives my design), and it does not mean that I will mock less. So, what do I do?
First, I verify external state, if there are any, like I’ve always done in addition to verifying behavior.
Second, some behavior can actually be regarded as a part of the public contract. For instance if an objects is supposed to post three messages to a log-queue, if it receives three notifications, this is behavior, and it can be regarded as public, at least for test purposes. This kind of behavior can easily be tested using mock objects.
Third, for private behavior, I try to be as loose as possible in my expectations. I often use Expect.Any() or Expect.AtLeastOnce() instead of Expect.Once() or Expect.Never(). In these cases we’re not really that interested in the behavior, we’re more interested in controlling the supply of objects to the SUT.
Your tests are your documentation
I’ve been reading alot about how your tests should be the key to understanding your systems behavior. Until now, I have thought that reading actual test code is the key. In one sense it is, if you read the test code, you understand in detail what that test tests. But honestly, no matter how much refactoring you do to make your tests understandable, looking at test code doesn’t really give you a quick overview of what is expected, as a whole, of a class.
But then I suddenly realized that the key is in the test names (method names), not in the test code. Let the test method names describe the expected behaviour of the SUT, reading those names should be sufficient to get an understanding of the obejcts responsibilites and limitations. This means that all requirements of a class must not only be tested by a test class, it also has to be explained explicitly in the test method’s names.
For links on TDD, go to the links page.
Tore Vestues


Hi!
Also, a good(long) test-name will naturally reduce the scope of the test.
And a leading “should” will open the class up for consideration
(should it? or has things changed?)
For the above points plus a lot more:
http://dannorth.net/introducing-bdd
(sikle,sikle)
Also: join the new farsott:
September 18th, 2007 at 13:08 (589)http://xp.meetup.com/27/