I think that there are some cases when multiple assertions are needed (e.g. Guard Assertion), but in general I try to avoid this. What is your opinion? Please provide a real word examples when multiple asserts are really needed. Thanks!

Edit

In the comment to this great post Roy Osherove pointed to the OAPT project that is designed to run each assert in a single test.

This is written on projects home page:

Proper unit tests should fail for exactly one reason, that’s why you should be using one assert per unit test.

And also Roy wrote in comments:

My guideline is usually that you test one logical CONCEPT per test. you can have multiple asserts on the same object. they will usually be the same concept being tested.

link|improve this question
feedback

5 Answers

up vote 18 down vote accepted

Great question.

I don't think it's necessarily a bad thing, but I do think we should strive towards only having single asserts in our tests. This means you write a lot more tests and our tests would end up testing only one thing at a time.

Having said that, I would say maybe half of my tests actually only have 1 assert. I think it only becomes a code (test?) smell when you have about 5 or more asserts in your test.

How do you solve multiple asserts?

link|improve this answer
1  
Like this answer - i.e. its OK, but its not, in the general instance, good (-: – Murph Sep 28 '10 at 11:45
I like this one too! – Restuta Sep 28 '10 at 21:15
feedback

I have never thought that more than one assert was a bad thing.

I do it all the time:

public void ToPredicateTest()
{
    ResultField rf = new ResultField(ResultFieldType.Measurement, "name", 100);
    Predicate<ResultField> p = (new ConditionBuilder()).LessThanConst(400)
                                                        .Or()
                                                        .OpenParenthesis()
                                                        .GreaterThanConst(500)
                                                        .And()
                                                        .LessThanConst(1000)
                                                        .And().Not()
                                                        .EqualsConst(666)
                                                        .CloseParenthesis()
                                                        .ToPredicate();

    Assert.IsTrue(p(ResultField.FillResult(rf, 399)));
    Assert.IsTrue(p(ResultField.FillResult(rf, 567)));
    Assert.IsFalse(p(ResultField.FillResult(rf, 400)));
    Assert.IsFalse(p(ResultField.FillResult(rf, 666)));
    Assert.IsFalse(p(ResultField.FillResult(rf, 1001)));

    Predicate<ResultField> p2 = (new ConditionBuilder()).EqualsConst(true).ToPredicate();

    Assert.IsTrue(p2(new ResultField(ResultFieldType.Confirmation, "Is True", true)));
    Assert.IsFalse(p2(new ResultField(ResultFieldType.Confirmation, "Is False", false)));
}

Here I use multiple asserts to make sure complex conditions can be turned into the expected predicate.

I am only testing one unit (the ToPredicate method), but I am covering everything I can think of in the test.

link|improve this answer
5  
Multiple asserts are bad because of error detection. If you have failed your first Assert.IsTrue, other asserts will not be executed, and you won't get any information from them. On other hand if you had 5 tests instead of 1 with 5 asserts you could get something usefull – Sly Sep 28 '10 at 10:52
1  
Do you consider it still bad if all the asserts test the same kind of functionality? Like above, the example tests the conditionals and if any of this fails, you should fix it. Does it matter to you that you may miss the last 2 asserts if an earlier one fails? – cringe Sep 28 '10 at 10:55
5  
I fix my problems one at a time. So the fact that the test could fail more than once doesn't bother me. If I split them up I would have the same errors come up, but all at once. I find it easier to fix things a step at a time. I admit, that in this instance, the last two assert could probably be refactored into their own test. – Matt Ellen Sep 28 '10 at 11:00
2  
Your case is very representative, that is why NUnit has additional attribute TestCase - nunit.org/?p=testCase&r=2.5 – Restuta Sep 28 '10 at 11:12
@Restuta: I had no idea you could do that! I'm using MbUnit, and have found a similar attribute: RowAttribute, so I can compress the above test, after the refactoring the last two asserts. – Matt Ellen Sep 28 '10 at 12:03
show 5 more comments
feedback

When I'm using unit testing to validate high-level behavior, I absolutely put multiple assertions into a single test. Here's a test I'm actually using for some emergency notification code. The code that runs before the test puts the system into a state where if the main processor gets run, an alarm gets sent.


    @Test
    public void testAlarmSent() {
        assertAllUnitsAvailable();
        assertNewAlarmMessages(0);

        pulseMainProcessor();

        assertAllUnitsAlerting();
        assertAllNotificationsSent();
        assertAllNotificationsUnclosed();
        assertNewAlarmMessages(1);
    }

It represents the conditions that need to exist at every step in the process in order for me to be confident that the code is behaving the way I expect. If a single assertion fails, I do not care that the remaining ones won't even get run; because the state of the system is no longer valid, those subsequent assertions wouldn't tell me anything valuable.* If assertAllUnitsAlerting() failed, then I wouldn't know what to make of assertAllNotificationSent()'s success OR failure until I determined what was causing the prior error and corrected it.

(* -- Okay, they might conceivably be useful in debugging the problem. But the most important information, that the test failed, has already been received.)

link|improve this answer
feedback

Having multiple assertions in the same test is only a problem when the test fails. Then you might have to debug the test or analyse the exception to find out which assertion it is that fails. With one assertion in each test it's usually easier to pinpoint what's wrong.

I can't think of a scenario where multiple assertions are really needed, as you can always rewrite them as multiple conditions in the same assertion. It may however be preferrable if you for example have several steps to verify the intermediate data between steps rather than risking that the later steps crash because of bad input.

link|improve this answer
1  
If you are combining multiple conditions into a single assert, then on failure all you know is that one failed. With multiple asserts you know specifically about some of them (the ones up to and including the failure). Consider checking a returned array contains a single value: check it is not null, then it has exactly one element and then then value of that element. (Depending on the platform) just checking the value immediately could give a null dereference (less helpful than the null assertion failing) and doesn't check the array length. – Richard Sep 28 '10 at 15:41
@Richard: Getting a result and then extracting something from that result would be a process in several steps, so I covered that in the second paragraph in the answer. – Guffa Sep 28 '10 at 16:42
feedback

If your test fails, you won't know whether the following assertions will break, too. Often, that means you'll be missing valuable information to figure out the source of the problem. My solution is to use one assert but with several values:

String actual = "val1="+val1+"\nval2="+val2;
assertEquals(
    "val1=5\n" +
    "val2=hello"
    , actual
);

That allows me to see all failed assertions at once. I use several lines because most IDEs will display string differences in a compare dialog side-by-side.

link|improve this answer
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.