Categories
Uncategorized

assertThat

I’ve just found a new feature in junit 4.4: assertThat()1. This gives you a much nicer way of specifying assertions than the usual assertEquals() or assertTrue(). Some examples from the docs above:

  assertThat(x, is(3));
  assertThat(x, is(not(4)));
  assertThat(responseString, either(containsString("color")).or(containsString("colour")));
  assertThat(myList, hasItem("3"));

This is both very readable, and leads to much improved diagnostic messages in failure.

It’s also (relatively) easy to extend to provide your own matchers (although check out hamcrest for some handy predefined ones). For example, I’ve just come up with this class to assert whether a collection is empty is empty or not.

class EmptyMatcher extends TypeSafeMatcher<Collection<?>> {
    @Override
    public boolean matchesSafely(Collection<?> c) {
        return c.isEmpty();
    }

    public void describeTo(Description desc) {
        desc.appendText("empty");
    }

    @Factory
    public static <T> Matcher<? super Collection<?>> empty() {
        return new EmptyMatcher();
    }
}

This is based on the example in the hamcrest tutorial. The only thing of real interest is the static factory method empty()2. This is what you would import static, so you can say:

  assertThat(setOfThings, empty());

This is more concise and leads to better error reporting than it’s predecessor.

  assertThat(setOfThings.size(), is(0));

One of the other nice things about using Matchers is that you can have side effects other than matching something. A great example is describedAs(). Say that you have:

  assertThat(a.getFrog(), is(not(nullValue())));

This would produce an error like:

Expected: is not null
Got: null

You can add in a description like this:

  assertThat(a.getFrog(), describedAs("frog", is(not(nullValue()))));

The error now becomes:

Expected: frog
Got: null

In the use I’ve put it to so far, this seems to be particularly appropriate for null values, which are otherwise quite unhelpful when a test fails.

I’ve completely switched my latest project to using assertThat(). So far, it seems to be leading to some nice readable code and I’m quite pleased with the results.

1 As an aside, “junit.org FAIL”: no javadocs, no news. The place is a mess.

2 I recommend checking out the chapter on generics in Effective Java 2nd Edition in order to properly understand the declaration here.

Categories
Uncategorized

Unit Testing falsehoods

My latest fad is looking at developing Mac apps (in Cocoa). Since the Leopard upgrade, Objective-C 2.0 has Garbage Collection. Congratulations Apple, you’ve lifted it out of the dark ages.

So, I’ve been trying to read up bits in ADC, but my time is limited. This means I turn to podcasts like Late Night Cocoa which I can listen to during my commute.

Today, I was listening to the latest Mac Developer Roundtable, Testing Testing Testing. Neat, I wondered how to do unit testing in Cocoa.

Sadly, the discussion was like asking blind people to critique a painting. None of the participants (save the host, Scotty) actually knew what Unit Testing was, or had ever done any. It was the most ill informed discussion I’ve had the misfortune to hear in a long while.

“asserts are just another form of unit testing.”

“Well, I know my code, so I don’t have to bother with unit testing.”

“Unit testing doesn’t give any value.”

(all paraphrased, but it’s the gist of things).

It’s weird, sort of like jumping back 10 years in time. Like the whole agile thing never happened.

Now, I completely accept that XCode might have terrible support for unit testing. It’s possible, I have’t got that far yet. Likewise, OCUnit might be hard to use. But that doesn’t negate the value of knowing that you’ve fixed something and don’t have to go back to it.

This is particularly surprising, given the high quality of what I’ve seen in Cocoa so far. Apple is big on design patterns. In particular, MVC plays a huge rôle in Cocoa apps. Controllers and Views might well be hard to test, because they’re part of the GUI. But your Model (which is the core of your application) should really be amenable to testing.

I really hope that the rest of the Mac development community isn’t so stuck in the dark ages.

Categories
Uncategorized

Practical Fascism

On my recent project at work, I’ve instigated a number of features:

  • An XSLT stylesheet that strips out all inline JavaScript and inline CSS before it ever hits the browser. Go-go Unobtrusive JavaScript!
  • Lots of jUnit tests:
    • Every piece of static HTML gets validated via RelaxNG (we had to use RelaxNG in order to allow mixed namespaces).
    • Ditto for every piece of XSLT.
    • A well-formedness test for every piece of XML.
    • A jslint test to check every file of JavaScript isn’t doing anything silly.
    • A “no tabs” test to ensure that there are no literal tabs in any piece of source code (in accordance with our local conventions).

I haven’t yet gotten around to integrating checkstyle. And I really need to write an XQuery parser that understands the ancient dialect we seem to be saddled with.

On the whole, these tests have proved to be a minor inconvenience up-front, often leading to groans around the office when the build breaks. But as a whole they’ve kept the code base clean and managed to detect problems early. So on the whole they’re a win. I’ll definitely be dragging them along to my next project.