Test Refactoring: extract an assert

When writing unit tests, I often see large sections of repeated asserts and asserts that are too low level:

void testAdd(){
	List list = new LinkedList();

	String s = "foo";
	list.add(s);

	assertEquals(1,list.size());
	assertEquals(s,list.get(0));
}

In this case the asserts are checking that the list contains the added item. This is done based on checking the size and checking of elements. The problem is that this logic often is repeated all over the place.

The smell can be removed by extracting an assert that spans the conceptual distance: it states what it does, but it doesn’t say how it does the job (extract method):

void testAdd(){
	List list = new LinkedList();

	String s = "foo";
	list.add(s);

	assertListContent(list,s);
}

void assertListContent(List list, Object... args){
	List expectedList = asList(args);
	assertEquals(expectedList,list);
}

This code can even be simplified by making List a member variable of the TestCase:

void testAdd(){
	list = new LinkedList();

	String s = "foo";
	list.add(s);

	assertListContent(s);
}

void assertListContent(Object... args){
	List expectedList = asList(args);
	assertEquals(expectedList,list);
}

It doesn’t look like it is adding much value, but I have seen enough unnecessary difficult to understand tests because of too many low level asserts. And when test are hard to understand, they are also hard to maintain. That is why I like my test methods short and clear (10/15 lines normally).

Advertisements

2 Responses to Test Refactoring: extract an assert

  1. Ryan says:

    Good point, but I’ll write 100 unit tests in a day and sometimes I pick out a common thread in the tests and be able to do that. Other times I won’t notice until later. I usually never refactor tests for the sake of maintainability until I go back and have to change something. In my experience, unit tests rarely need the kind of maintenance that functional code does.

  2. Lars Vonk says:

    Hi Peter,

    I see your point, but I don’t like extracting assertions and prefer to write them out (even if this duplication) for the following reasons:

    – Readability of your tests. If you extract your assertions you have to scroll up and down, maybe even between superclasses to see what is actually asserted.
    – If you run you unit tests from within eclipse you can click the assertion that failed and your view will go to the test method that failed. If you extracted the assertion your view will go in the method that contains the assertion line, and in this case that is the assertListContains. Now if you would have to assert three list you can not see immediately anymore which assertion really failed.

    I prefer to have some comments put in your assertion, so instead:
    assertEquals(1,list.size());
    do something this:
    assertEquals(“Expected exactly one item in list x”, 1,list.size());

    Lars

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: