Classic vs Mockist, TDD vs BDD

I’ve been having constant issues with Behavior Driven Design using xUnit tools. For those that don’t know what behavior driven design means check out Dan North’s introduction. When writing tests you can choose from a number of approaches. I feel I’ve followed an evolutionary chain through the most popular. Most people start with CWT, or Coding While Testing. This is an approach where the tests are written with the code, not necessarily before but along side. People take this “feel good” approach in order to cover their code with tests and to gain confidence that their code won’t break without them knowing why/where. Eventually tests become brittle and break all around and the tests become a burden to maintain. Some people evolve into TDD or Test Driven Design. This is where the test is written first in an attempt to achieve better design. When I evolved this far I was still struggling in the “implementation zone”. That’s where most developers get their mail delivered. The implementation zone is where the major concern is how things work. You can’t rest well unless you know exactly how things work beneath a method call. There are no surprises because everything is understood. Doing TDD while living here leads to “White Box” tests. These are tests that mirror the implementation of the system. These test scream immediately when the system change in the slightest. It’s no fun.

Later I learned about the Behavior Driven approach which lead to my understanding DSLs, or Domain Specific Languages. Actually I picked up my understanding of DSLs when I started using JMock, which is still one of my favorite tools. I started to remember why programming languages were invented. “Code is for Humans” became my mantra. I stopped caring about how code worked and started concerning myself with why code was written. With today’s systems rivaling NASA in their complexity it becomes impossible to obsess over every implementation detail. It’s more natural to trust that something works through an automatable specification that says it works. Its hard to put in English, but there’s a subtle difference in how I look at code compared to how I see most of my co-workers look at code. I rely on a system of trust which helps both in design and in debugging. I digress.

This morning I began reading Martin Fowler’s revised write up on Mocks vs. Stubs. If you do any automated testing of your system at all I demand you read this article. If you’ve read it in the past (as I had) I demand you read it again because it’s updated. If you read it last week then I demand you read it to your 5 year old tonight at bed time. The point is that Martin makes very good distinctions on what he calls classic TDD and Mockist TDD. He explains the difference between state verification and behavior verification. He explains it in a way that shocked me, because I’d classify myself as a mockist. The entire time I obsessed over implementation being secondary to design I see how and why the mockist frame of thought can easily shackle your design to your implementation details. I almost wanted to change ships, jump on the classical bandwagon. However the article very fairly points out several flaws in both approaches while not condemning either. In the end the choice is left to you. Well done Martin. Well done.

I titled this post, “Classic vs Mockist, TDD vs BDD” not to align BDD with the mockist approach though it fits better. The truth is that you can use Martin’s classic TDD style when doing BDD and vice versa. There really isn’t much of a difference between classic or mockist, TDD or BDD. It’s all really a matter of style as all these approaches aim in the same direction. Its similar to comparing Baptist to Methodist religions. There are differences but one is not more true than the other and its the faith or general direction that both point to that makes them equally as important. Here’s what’s really important.

Back to my problem. I posted on Stack overflow yesterday asking the question of how to avoid so many mocks. I have yet to receive a solution to the core problem I’m seeing. If you or someone you know has a mastery of TDD please chime in. I’d love to finally have a good discussion on how to solve a complex problem using the practice. I feel like I’m 80% there but I’m missing one piece of the pie.

Ten T.D.D. Commandments

Update* A while ago I thought it was cool to use the file system during a test but a little bunny taught me otherwise. I’ve removed a redundant commandment as well.

Inspired by Ashcroft… not that Ashcroft but this one.

Ten Commandments of Unit Tests

1. I am the class being tested. Thou shalt not test any other class but me.
2. Thou shalt NOT write implementation without a unit test.
3. Thou shalt ensure the bar is red before any code is written.
4. Thou shall NOT write two tests which depend upon each other
5. Thou shall NOT test private methods.
6. Thou shall NOT access files during unit tests.
7. Thou shalt always refactor both test and implementation code after every green bar.
8. Thou shall NOT worship (or test) any false classes (mocks).
9. Thou shall NOT define more than one behavior in a unit test.
10. Thou shall NOT commit code without green bars on all tests.