CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Ian Cooper [MVP]


Classicist vs. Mockist Test-Driven Development

One thing that came up in a couple of sessions of Altnetconf UK was the old saw of classicist vs. mockist approaches to TDD. Martin Fowler has a great, and updated, article on the distinction between the two approaches here. Now I have to confess to being a classicist. I tried being a mockist, but I gave it up because of the dangers of over-specified software. Now I tend to favor test doubles for the areas that are difficult to get under test otherwise as per Michael Feathers. We are also much more inclined to use a stub or fake than a mock.

Now some folks seemed to feel that if you had used concrete dependencies or associations in a test, you were not writing a unit test, and thus not using TDD properly. I see the origin of the unit test mantra, Fowler calls TDD in the classicist model mini-integration tests over unit tests, but I reject the latter accusation that this is not, somehow, TDD. The spirit of TDD in my reading, of Kent Beck, never precluded the use of concrete collaborators.

Maybe its time to stop thinking about unit tests and integration tests, with the implicit zero tolerance for collaborators in unit tests, but simply tests and acceptance tests with the latter being more coarse-grained than the former.


Certainly one advantage for classicists is that we don't get 'an interface for everything' and end up with ICustomer, but interfaces where actually want points of extensibility i.e. where we have role that can have multiple implementations, or at boundaries such as layers. We don't really have to worry about using solutions such as TypeMock to mock a concrete dependency, and so avoid proliferation of interfaces, because we are often more happy with the concrete object itself.

Usefully, there seems to be a convergence between hard-to-test code for classicists, which is where we tend to deploy mocking frameworks, and the places where we need interfaces, so difficulty seems to help flush out these design points.

I would also suggest that people look to the notion of what Rebecca Wirfs-Brock and Alan McKean call sub-systems or object neighborhoods within the domain. Within a neighborhood I would have few doubts around allowing concrete collaborators in tests, it's okay to play with the other kids in your neighborhood, but outside of that subsystem, you probably want to use a test double to reduce stranger danger. Of course the class to replace with a test double is the facade which you should pass through to get to that neighborhood anyway, once again reinforcing the notion of TDD driving good design.

 

 

 



Comments

Jimmy Bogard said:

I do agree that over-eager mocking leads to fragile tests.  The mistake is to use static mocks where dynamic mocks, stubs, fakes, or dummies would work just fine.  Interaction testing has its place, but overuse leads to over-specification.

# February 4, 2008 9:32 AM

Christopher Bennage said:

Does the term "unit" in "unit test" imply that there is just one thing being tested.  I'm okay if you want to use concrete collaborators, but I'm a little resistant to calling those "unit tests".  We need a better vocabulary for all this stuff.

# February 4, 2008 10:12 AM

Zubair Khan said:

Amen Ian, this is exactly the point I tried to make at ALT.NET UK. There's always a balance to applying practices, and I don't think TDD forces anyone in to an IEverything corner. I wonder if this could be something that the "BDD is TDD but a bit better" discussion could have made clearer for me.

# February 4, 2008 10:12 AM

So bored said:

The whole "state based vs. mockist" thing is a total fabrication of Martin Fowler.  There's no "versus" to talk about.  It's like discussing "hammerist vs screwdriverist" woodworking.  There are tools that are useful for the different things you need to do in TDD.  Learn to use the tools.  Learn to know when to use each kind of tool.  End of story.

# February 4, 2008 10:26 AM

So bored said:

Ian, please write an article about "Hammer-ist vs. Saw-ist" carpentry.

# February 4, 2008 10:27 AM

Jason Neylon said:

Perhaps mocking framework should come with a "learn about test doubles first" warning on them? (like Castle Windsor has: www.castleproject.org/.../index.html)

I think developers go through a period of over-mocking in their tests whilst learning these frameworks. Once I learnt more about test doubles it was far clearer to me where mocking was useful and where it was simpler  to use fakes etc.  

# February 4, 2008 10:29 AM

Mike Hadlow said:

We had a very similar argument in our discussion on IoC and DI. Roy Osherove made an interesting point that doing unit testing forces you do DI unless you use some heavyweight tool (like Typemock :). So adopting the practice implies adopting an architecture. Sure you can give up unit tests and rely on integration tests, as one chap proposed, but I felt that's a step backwards.

So then we started arguing about how fine grained do you make the thing-under-test. I think it's obviously wrong to think class == component and I like the idea of sub-systems, but the scale of your 'sub system' or 'object neighborhood' directly affects how finely grained your tests can be. It's easy to fall into the trap of requiring so much setup to test a large component that it never gets properly done.

I guess I fall more into the mocking camp than the test double one, maybe I'm one of those developers that Jason says go through a period of over-mocking. It's a long period in my case :)

# February 4, 2008 10:56 AM

Colin Jack said:

Yeah totally agree, in fact this is one of my favorite testing topics :)

I certainly don't follow a zero-collaborators approach especially when we're talking about domain level testing.

# February 4, 2008 11:41 AM

Ian Cooper said:

@Christopher

I think this is my point. We never used to require unit tests by the strong definition of 'everything else must be mocked' for TDD. The operative definition of unit at the time of course was Michael Feathers, which related more to painful tests than divorcing ourselves from concrete collaborators.

The mockists have moved to a position where now, any concrete dependency, is bad in TDD. Though I assume they don't include value types in that assertion.

I'm just saying that I have not moved with them.

# February 4, 2008 12:58 PM

Ian Cooper said:

@So bored

The point is that a number of people made the effective statement that 'If you use a hammer, you are not doing carpentry, carpenters only use saws'.

# February 4, 2008 1:00 PM

Greg Young said:

There is something to be said also for architecting for a given type of testing. We tend to aim for a non-mocked environment and heavily focus on making that easy for ourselves using things like messaging patterns as opposed to direct interactions.

# February 4, 2008 11:35 PM

Colin Jack said:

@Greg

When you say you use messaging patterns though what do you mean, I think I may be designing the same way but I'm not 100% sure.

# February 5, 2008 7:50 AM

» Daily Bits - February 5, 2008 Alvin Ashcraft’s Daily Geek Bits: Daily links, development, gadgets and raising rugrats. said:

Pingback from  » Daily Bits - February 5, 2008 Alvin Ashcraft’s Daily Geek Bits: Daily links, development, gadgets and raising rugrats.

# February 5, 2008 8:23 AM

Greg said:

@Colin

I will blog ... got a backlog so may be a day or two.

# February 5, 2008 2:37 PM

Greg Young [MVP] said:

Now that the title has grabbed your attention no I don't really think that mocks are a code smell

# February 13, 2008 4:52 AM

Greg Young [MVP] said:

Mocks are overused, why deal with mocking dependencies when you can avoid them?

# February 13, 2008 9:28 AM

Alec Lazarescu's Blog said:

I'll begin a series of posts that in no small part will serve as summaries/reminders to myself on various

# February 18, 2008 2:54 PM

Steve Freeman said:

Who are "the mockists" and where is their secret hideout from where they plan world domination? A little less Strawman, please.

# May 18, 2008 7:44 AM

Steve Freeman said:

Can we find a way to talk about TDD styles without being pushed into opposing corners? We don't like many of the stylistic failings you complain about either (for example www.mockobjects.com/.../test-smell-everything-is-mocked.html). If you're citing Wirfs-Brock, then we already agree on a lot of ideas, and there's more than one route to improving what people do.

We see a lot of TDD with mocks where the coders haven't really understood the point: too much asking over telling, not enough of a domain model, unfocussed interfaces (like ICustomer).  We're trying to get the ideas across, but there's a lot of noise on the subject nowadays.

And one more thing to think about. One of the most valuable results we find from interaction-based testing is the idea of driving the design of  a type from the needs of its clients. We can do it with clusters of concrete objects, but we find that working against interfaces helps us be clearer about what the relationships should really be.

# May 18, 2008 8:04 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!