What your tests don't need to know will hurt you

I just finished reading Brian Marick’s article, “Mocks, the removal of test detail, and dynamically-typed languages”, which focused me on a design technique I use heavily: awareness of irrelevant details in tests. Referring back to the four elements of simple design, I focus on irrelevant details in tests in order to help me maximize clarity in production code. Please allow me to sketch the ideas here.


This is a companion discussion topic for the original entry at http://blog.thecodewhisperer.com/permalink/what-your-tests-dont-need-to-know-will-hurt-you

One minor point: "I use should eql() here, which translates to assertSame()" actually, that's the same as assertEquals(). If you want assertSame() you need to use equal().

ri BasicObject#equal?: "is used to determine object identity"

This is a great article. Would you be able to expand on/give examples of the refactorings you mention in your second-last paragraph, say in a future post?

A thought popped into my head after seeing how your controller test didn't care what it passed, just that it forwarded some Object. (I also wondered if there was a test for the "passed in nil" fail path.) Anyway, that thought:

"Do you need to test the controller at all?"

What drove you to consider writing the test for this in the first place?

I got that wrong. Thanks. I have fixed it.

I can't commit to doing that, but I highly recommend following the links and looking for examples there. Also, look at the books I have listed at my librarything.com account (jbrains) for even more and better examples.

This controller method does more than just the behavior I checked in that one test. Even if it didn't, invoking a method and giving its result to another method is not usually Too Simple to Break. I agree that's a judgment call.

As for the nil case, I don't remember if I have a test for that. I'll have to look.

I created a plugin for groovy/grails projects that takes this principle to the next level called "build-test-data". In grails, domain objects have constraints on them that determine which fields are required and what kinds of validation they need in order to be persisted.

The plugin adds a "build" method on all domain objects that will create and save a new instance of a domain object with all required fields populated with dummy data. You can then pass in any fields that you actually want to have specific values that matter to your test.

It turns your example above (groovy style code) from this:

Posting.build(
title: "irrelevant title",
content: "irrelevant content",
queuedAt: null,
published_at: null
)

Into this:

Posting.build()

You don't have to specify any values that you don't care about, it populates title, content, queuedAt, and publishedAt for you. If you did care about the title in your test, you'd just use:

Posting.build(title: "title that matters for test")

I'm not aware of any other rails/django/merb type frameworks with this addition to their testing frameworks, but I think it'd be possible to create something similar for all of them. With rails active record interrogation of the database constraints, it should be possible to do the same kind of thing.

Very neat, Ted. A good-looking implementation of the ObjectMother pattern. As you say, I imagine it would take relatively little effort to create a plugin for Rails. Thanks for sharing.

I just found a nice, simple example of this. Read the section "Examples all have the same structure" in http://concordion.org/Techn...

just wanted to mention that the link to the test data builder pattern is broken

At long last, fixed. Thanks.

In the mean time it broke again ;)

I just followed the link and it works now. :shrug: