On the topic of assertions

Every assertion should be thought from the standpoint of

  1. What was expected
  2. What actually happened

Translation: assertTrue should always, always have a message.

Consider the following:

assertTrue(mv.getViewName()
    .startsWith(myController.getSuccessView()));

This will only return “assertion failed”. Which is great, but how do we know what happened? If this is buried on one of the lunt automated remote builds, how am I supposed to know what is going wrong? Which is the expected? What actually happened?

A much better version of the same looks like this:

assertTrue(
    "Was expecting something like "
        + myController.getSuccessView() + " but was "
        + mv.getViewName(),
    mv.getViewName()
        .startsWith(myController.getSuccessView()));

Same assertion, but now it tells me more specifically what’s going on and I can fix bugs with it. Once I set this on the test, it becomes easy to see what was going on.

I recently had a Saturday with some other Bay Area developers where we did a lot of thinking about testing, so expect some more advice in the future as I collect my notes.

Remember the goal of unit tests is to “find bugs” (thanks Harry!). An assertion without an associated message merely notifies you that a bug occurred but doesn’t actually “find it”. As you are writing your unit tests, make sure you find it as well.

technorati tags:, , ,

2 thoughts on “On the topic of assertions”

  1. I’ve never quite been able to reconcile their redundancy with the test names.

    I’m okay with assertion descriptions, but I do think that if your tests are well named and match the assertion (and there’s just one), it still remains pretty clear. ex:

    public void Test_ViewIsPopulatedWithMySuperDuperFlag_When_UserIsSuperDuper()
    {
    // blah blah
    assertTrue(view.SuperDuperFlag);
    }

    I think the report from a test like that is totally readable. I like having very descriptive test names, and if you have them the descriptions sometimes seem redundant.

    Now, if you have one of those cases where the assertion is not so obvious, or you’re (for a decent reason) doing multiple assertions, descriptions are perfect.

  2. Well, that’s probably an exception. If your test name creates a redunancy you probably don’t need to add it twice out of respect of the DRY principle. However under some circumstances (integration tests come to mind, and there may be others) you need more than one assertion per test so the build time doesn’t become a problem (long build times can kill a project, so some project managers tell me).

    At other times I worry about the granularity of the tests becoming a barrier to non-developers who want to know the status of the project. I fear that so many individual tests (as opposed to multiple assertions inside an overarching test) may add to confusion if your audience (the people who read the junit results) is composed of more than developers. It brings to bear the debate of one assertion per test vs. one assertion per scenario. No silver bullet of course.

    So although Rob’s point is indeed an important clarification, still keep in mind that if you have to have more than one assertion, do make sure you add strings to them. Also make sure those methods really are descriptive.

Comments are closed.