Single Assertions Do Not (Necessarily) Check Single Expectations

A friend recently criticized the way that I write unit tests.

According to him, we should only test one expectation at a time; so, we can only have one assertion per test.

Now, I completely agree with the “test only one expectation at at time” philosophy. However, I completely deny that that implies we should only have one assertion per test.

Unfortunately, I’ve noticed that a large portion of developers buy into this mantra; and under some circumstances, it actually has very good results. However, it also has the potential to block developers from writing clear and meaningful tests.  

Confusing Strategy for Tactics

For this discussion, I will use the arrange-act-assert paradigm of software testing.

Suppose that I wanted to remove duplicate items in a javascript array. The following function could provide that functionality.

In order to test the “uniq” function, I could use the following jasmine code

Superficially, this test seems to follow the “one expectation; one assertion” rule. However, consider what it means for the test to fail.

What postconditions could make this a failing unit test? From the top of my head, I can think of the following scenarios

  • The result is not an array
  • The array has more or less than 4 elements in the list
  • Index zero of the array is not 0
  • Index one of the array is not 1
  • Index two of the array is not 2
  • Index three of the array is not 3

This implies that the following unit test is at least as powerful.

Tasting the Forbidden Fruit

Even though the first unit test had only one assertion, it actually checked at least 6 different postconditions.

This proves that the “one expectation; one assertion” rule does not work (in general); so, feel free to use as many assertions that you want and need.

Personally, I find that aiming for “one expectation; one assertion” makes me write cleaner tests. However, I’ve also found situations where it makes me write complex or cumbersome tests. My milage using “one expectation; one assertion” varies depending on the type of test.

I would recommend everyone at least try to aim for the ideal of “one expectation; one assertion”, but only as far as it helps you write good tests. At that point, you should throw it away.

Advertisements

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