Names Should Be Expressive When Writing Tests

It is still surprisingly common to see test methods named “test” followed by the name of a some method that’s going to be called. Sometimes you get a few words mentioning some other internal detail, like

@Test
public void testLogin_Null(){...

This sucks. I’m amazed people still do it.

It doesn’t say anything (or only very little) about the scenario.

It doesn’t say anything about the behaviour required in that scenario.

It says “test” when I already know it’s a test. The annotation, for example. And the fact that it’s in a test case class.

It says the name of one method that this test calls, ignoring others, and sometimes that method name doesn’t even exist any more.

It tells me that some test data is going to be null, but it doesn’t tell me anything about what should happen in that case, or why.

There’s no excuse for this. It’s so easy to pick a name that expresses what scenario you’re trying to construct, and what behaviour you expect from your code in response. Given an expressive name, others can confirm that the scenario is as intended,, that the behaviour is as intended, and they’ll be more confident that they’re complying with the original intent as they make changes in related code, or fix bugs.

The First Rule Of Test Naming – Say What The Code “Should” do

@Test
public void shouldThrowExceptionWhenUserNameIsNull(){...

This tells me, the reader, what the component should do in a particular circumstance. I can read all the test method names to understand the full range of responsibilities of the unit-under-test.

@Test
public void shouldCompleteTimeSheetWhenItIsFridayMorning(){...

@Test
public void shouldDrinkBeerWhenItIsFridayNight(){...

@Test
public void shouldNotGetOutOfBedBeforeTenWhenItIsSundayMorning()...

@Test
public void shouldNotWorryAboutLongNamesInTestMethods(){...

The Second Rule Of Test Naming – Describe The Behaviour, Not The Methods Called

This is the same as the first rule, just stated differently.

There is not a one-to-one relationship between methods in the unit-under-test and the test cases. Don’t write test cases by writing one for each method that can be called.

Anyway, you can’t do that if you’re writing the test first, and you are writing the tests first, aren’t you?

Instead, write methods that describe the behaviour of the unit-under-test. When you’re thinking about what the component should do, when you’re thinking about the edge-cases and awkward conditions you’ll have to code for, when you’re discussing requirements with stakeholders, document all these things as test methods with readable names that express what should happen in particular circumstances.

The Third Rule Of Test Method Naming – Imagine Being The Reader

This is the same as the first and second rules, just stated differently.

Imagine you’re the person who will be reading these tests for the first time in the future. What will they want to know? How can you write it so that you are telling that reader, very clearly, what the unit-under-test is meant to do in all the various circumstances it has to contend with. What business rules does it have to obey? What are the requirements? What are the special cases and edge conditions?

Don’t try to tell the reader how the component fulfils these responsibilities – do that in the implementation code.

Tell the reader what the responsibilities are.

Don’t write tests from the perspective of things you know about your implementation and want to check, write them from the perspective of the reader wanting to know what behaviour they have to preserve to make sure this thing still behaves correctly.

Instead of:

public void testSignUp_null(){...

public void testSignUp_blank(){...

How much more expressive and clear is it to say:

@Test
public void shouldThrowExceptionWhenUsernameIsNotProvided(){...

@Test
public void shouldCreateAuditEntryWhenUsernameIsNotProvided(){...

@test
public void shouldStillAllowSignupWhenPhoneNumberMissing(){...

The word “when” is should’s ally when it comes to test names. shouldDoThisWhenThat. Some say it reads better if you start with the “when”, and that’s just fine.

@Test
public void whenTestNameIsBadShouldReplaceIt(){...

I prefer to put should first, because it sounds more forceful, more direct, less passive:

@Test
public void shouldReplaceTestNameWhenItSucks(){...

The Only Real Rule Of Test Method Naming – Always Use “should”

This is nothing new. I thought the “testMethodX” style died out in the last decade. Why do I still see it everywhere?

Postscript

John Ferguson Smart in his excellent book “BDD In Action”, writes:

Language influences thought patterns. The words you use influence the way your message is perceived. Consider the following subconscious dialogue that our brains go through when reading a requirement:

Requirement: A new Frequent Flyer member status must be Bronze.
Brain: Yes Sir, very good Sir, right away Sir!

or

Requirement: A new Frequent Flyer member status should be Bronze.
Brain: Should it? Are there times when it might not be Bronze? What about special deals from marketing where they start out as Silver? What about if they’re transferring points from a partner airline?

Only one word has changed, but the way we receive the information is quite different. The word “should” invites a question: “should it?” “Should” helps us justify why we want a class to provide a particular service, or to perform a particular task. Should also implies that any requirement, at any level, can be questioned, leaving communication channels much more open.

See a good discussion of different naming strategies here – http://www.petrikainulainen.net/programming/testing/writing-clean-tests-naming-matters/

Advertisements
Posted in Clean Test Code, JUnit
3 comments on “Names Should Be Expressive When Writing Tests
  1. rborowiec says:

    Great post.

    I really love the idea. For some time I used the “should” way of naming, but I moved a step forward. I realized, that if “should” is used for all methods, it is maybe better to skip it?

    I such a case I would have:

    throwsExceptionWhenUsernameIsNotProvided

    createsAuditEntryWhenUsernameIsNotProvided

    allowsSignupWhenPhoneNumberMissing

    In my opinion the readability is still good. What is your opinion?

    I blogged about some time ago: http://blog.codeleak.pl/2013/07/unit-test-names-describe-features.html

    • Todderz says:

      You make an excellent point.

      Don’t repeat yourself, right?

      Makes me wonder why I’ve never thought of that. I think perhaps it’s because I so often find myself needing to convince others to stop using the “testMethodA, testMethodB” style, and being able to say “always start with ‘should'” is so easy to say and so easy to follow.

      I think you’ve hit on a clear way of expressing the principle underlying that rule, which is that “test names describe features”.

      When you understand the principle underlying a rule, you can make your own rules, and you’ve done that very effectively.

      Thanks for the idea!

  2. Charles Roth says:

    I think keeping the “should” is useful. For one thing, I often have utility methods inside the test class, and it’s nice to be able to know at a glance (w/o looking at the annotations) which is which.

    In fact, I take that a step further, and use prefixes for different ‘standard’ kinds of methods. E.g. I may have several @Test’s that begin should…(), which in turn call a utility method that asserts some conditions… so that in turn is (of course) called assertSomethingOrOther.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: