InfoQ

InfoQ

News

My Bookmarks

Login or Register to enable bookmarks for unlimited time.

The content has been bookmarked!

There was an error bookmarking this content! Please retry.

"Classic" versus "Mockist" TDD, Distinction Real?

Posted by Mike Bria on Jan 22, 2009

Sections
Process & Practices,
Architecture & Design,
Development
Topics
Unit Testing ,
Software Testing ,
Software Craftsmanship ,
Agile
Tags
jMock ,
Mocks ,
Design by Contract ,
TDD

Hot in the Test-Driven Development Yahoo group this week is a discussion concerning the perceived continuum between the so-called "Classic" and "Mockist" approaches to TDD. Steve Freeman, Nat Pryce, Michael Feathers, Dale Emery, and many more discuss terminology and describe their approaches. The discussion also debates whether there even really exists such a continuum, and if so, what distinguishes the approaches that represent it's extremes?

After stating he "feels inclined to the classic-TDD approach", Olaf Bjarnason started the 70+ entry discussion with this question to the group: "What made you switch [to "mockist"] from classic, if you were there before? How does the new method feel?". Many of the early responses though centered more around a challenge Olaf's thread title, "Classic/Mockist discussion". Is there really a need for such a binary distinction?

Nat Pryce, co-creator of JMock, expresses his feeling:

I think the whole division of TDD practice into "mockist" vs "state based" is pointless, distracting and does a disservice to people trying to learn and use TDD.

Mock objects are just a tool. They are one of many tools that you need to use when doing TDD. Like any tool, they are designed to help solve a set of problems in a specific context. Outside that context they do not help and can be a hindrance.

If this is the case, how then does one know when to apply this "tool"? How does one know to test "state", namely without a mock, versus asserting behavior, namely by using mocks?

Dale Emery chimes in to describe how he typically makes the distinction:

Lots of people use the distinction of "state-based" versus "behavior-based." I use a twist on this. I think "result" versus "protocol". If the essence of the test is whether the UUT produced the correct result, I don't usually need a mock for that. If the essence of the test is whether the UUT properly executed its role in a protocol--i.e. whether it sent the right messages to the right collaborators, given the starting conditions and the stimulus--I use mocks to represent the UUT's direct collaborators.

Lior Friedman asserts that a mock's place is in representing a contract:

For me usage of mocks indicate the existence of a "contract" between the class under test and another class which is used. And the goal of the test is to verify that the contract is fulfilled.

Charlie Poole pitches in with his gauge on when state-based is the way to go:

I'd use state-based testing on an object if I had no other way to observe it's behavior - that is if /all/ the call did was change an observable state of the object. Assuming the object actually did something, I'd want to verify [with a mock] that it did it.

Adam Sroka on when he uses a mock:

For my own part, I *always* mock at system defined boundaries (e.g. filesystem, network, database, etc.) I usually mock when I want to elicit loose coupling between an interface and it's client in a top-down direction. And, I generally don't mock when the object I am interacting with is small and easily faked/stubbed.

As the thread goes on, and as may be highlighted by the above sound-bites from it, there is a recurring observation that while many of these ideas are similarly themed, they don't seem to share a commonly categorizable, named approach beyond "We do it sometimes, but not others". Further, each (with the exception possibly of Sroka's statement about "top-down") tend more to the following: The decision to mock is being driven by the design, as opposed to the converse, where the design is driven by the mocks.

Regarding this idea of using mocks to drive design, Michael Feathers gives an example:

To me, the real meat behind the whole subject is just how far people are willing to push "tell, don't ask." Mocks are a prop for a design approach.
...
Imagine you have some object and you want to get report of its errors:

    class Errors {
        int errorCount();
        Error getError(int index);
    }

    Errors errors = object.getErrors();


That's an ask. We can do state-based testing of the Errors object in the test.
To make it a tell you'd move to this:

    interface ErrorReceiver {
        void accept(Error error);
    }

    ErrorReceiver receiver = ...;
    object.reportErrors(receiver);

We can set expectations on a mock receiver and pass it during testing and use a "real" class in production.

Later, largely in response to a post by Steve Freeman (another co-creator of JMock) describing his partner Nat Pryce's categorization of some "mock-worthy peer objects" ("Dependencies","Notifications", and "Policies"), Feathers (and also Colin Jack) assert that the design ideas the duo have been putting forth in fact exist at the core of this "mocks as a tool to drive design" philosophy. Further, more to the point of this thread, that when people talk of a "mockist TDD approach" they are referring in large part to these design ideas, and that the recurring confusion about "Classic vs Mockist TDD" could be reduced if these collection of ideas had a more concrete name.

As Pryce reminds the group, he and Freeman have a book in the works that may just provide some this clarification being requested. He also points the group to a write-up of his on "State vs Interaction Based Testing".

So, keeping it real, this conversation is really not a new one (Google it), but it is it seems a recurring one. Is there a "Classic TDD", and does it mean "Design begets Mocks"? Is it characterized by something else? Is there "Mockist TDD"? Is it characterized by a "Mocks beget Design" philosophy? "Tell, Don't Ask"? Is it something altogether else? Either way, is it really a "this OR that" thing, or more likely "this for these AND that for those"?

Of course, as always, this news is simply a [hopefully objective] highlight of the Yahoo group discussion, and as such only a piece of the puzzle. Read it for yourself, as well as other sources, and tell others here and/or in the discussion what your experience says.

  • This article is part of a featured topic series on Agile
bad link by Clay Smith Posted
Re: bad link by Mike Bria Posted
Re: bad link by Rhys Campbell Posted
Re: bad link by Mike Bria Posted
Perhaps by Michael Hedgpeth Posted
Test what you want to expect by Rhys Campbell Posted
  1. Back to top

    bad link

    by Clay Smith

    Could you provide the real link to the discussion group? I don't find some-site.com to be particularly useful.

  2. Back to top

    Perhaps

    by Michael Hedgpeth

    Perhaps it's more of an argument among those who haven't done TDD for a while. Talking about the distinction and leading people towards state-based testing will keep then from being too extreme and entering an unfortunate place I call "mock hell".

    With the knowledge of mocks in hand and the understanding that they are to be used sparingly, new TDDers will find themselves in the balanced place that the gurus on the list (above) are at.

  3. Back to top

    Re: bad link

    by Mike Bria

    Hm, sorry Clay, not sure what you mean. All seems fine to me?

    Cheers
    MB

  4. Back to top

    Re: bad link

    by Rhys Campbell

    final link in the post "Yahoo group discussion" goes no where:
    [quote]
    Of course, as always, this news is simply a [hopefully objective] highlight of the Yahoo group discussion, and as such only a piece of the puzzle. Read it for yourself, as well as other sources, and tell others here and/or in the discussion what your experience says.
    [/quote]

  5. Back to top

    Test what you want to expect

    by Rhys Campbell

    I personally think its somewhat of an inane argument. If the test is requiring interaction, use a mock. if it requires a change of state use an assert. How this picked up traction.. I really don't know..surely there is some code to written team... get to it!

  6. Back to top

    Re: bad link

    by Mike Bria

    Got it, thanks!

Educational Content

New-age Transactional Systems - Not Your Grandpa's OLTP

John Hugg discusses high volume transaction processing applications with high and low frequency profiles, and how VoltDB can be used for that purpose.

Cool Code

Kevlin Henney examines code samples to see what can be learned from them starting from the premise that one won’t write great code unless he knows how to read it.

Collaboration: At the Extremities of Extreme

Jason Ayers share the observations he made watching a team of developers collaborating in real time on the same code base, pushing XP, pair programming and continuous integration to their extremes.

Yesod Web Framework

Michael Snoyman presents Yesod, a web framework written in Haskell and containing a web server, templating, ORM, libraries (templating, gravatar, etc.).

Transactions without Transactions

Richard Kreuter and Kyle Banker on how to avoid classical RDBMS transactional systems by using compensation mechanisms, transactional messaging or transactional procedures.

Attila Szegedi on JVM and GC Performance Tuning at Twitter

Attila Szegedi talks about performance tuning Java and Scala programs at Twitter: how to approach GC problems, the importance of asynchronous I/O, when to use MySQL/Cassandra/Redis, and much more.

10 tips on how to prevent business value risk

One category of risk that project teams need to ensure they address is business value failure – delivering a product that fails to provide value for the business investor.

Interview: Software Systems Architecture: Working With Stakeholders Using Viewpoints and Perspectives

InfoQ spoke to the authors of Software Systems Architecture on a couple of new topics, the System Context viewpoint and Agile, which have been added to the second edition.