views:

96

answers:

5

For example the Equals method. a should equal b and b should equal a. Would you say it is OK to check this in one test case using two asserts like the following:

[Test]
public void Equals_TwoEqualObjects_ReturnsTrue()
{
    var a = new Something();
    var b = new Something();

    Assert.That(a.Equals(b), Is.True);
    Assert.That(b.Equals(a), Is.True);
}

Or do you think this should be done in two separate tests so that you won't have two asserts in the test?

I'm thinking having two asserts in this case may be cleaner, because I am not sure what I would call the two separate tests, and I am kind of thinking it doesn't matter which one of the asserts that break the test. But anyways, I am curious to know what others think about this since I am kind of a newbie in this area :)

+5  A: 

I think it's absolutely fine to have them in one test.

The "one assert per test" idea feels more like dogma than anything useful to me. Be pragmatic with your testing.

Yes, test one piece of functionality per test - but don't restrict yourself to one assertion.

Jon Skeet
I 'undo' -1s without comments explaining why. That nets the poster 8 points. The point Said Horse was making is that you need to consider the context and not be having a 'Best Practice' like 'one assert per test' stop you from thinking.
Ruben Bartelink
@Ruben -- I think you should only upvote something you believe is helpful, not vote based on other people's voting patterns.
tvanfosson
@tvanfosson: It's people like me who have gotten The Horse where he is today so :P I cast the vote when the score was -1 though. The aim of the comment and the +1 was to get the voter to explain the -1. Sadly that hasnt happened. I think the "No dogma" message is good and the "Its OK Not..." message is bad. This makes it a zero for me. But not a -1 ordinarily. But I guess my post says that. But you're right - voting patterns are mangled enough without me adding votes for meta reasons.
Ruben Bartelink
+1  A: 

I would have them in two tests as if one of the links is incorrectly set up you will know exactly what one, remember a Unit test tests the smallest possible unit.

Burt
+4  A: 

I'm going to say you have to have both tests in one place. It's not enough that one object equals the other and some other one object equals another. It's that the same two objects equal each other at the same time.

The intent of your test (to test that equals is commutative) is much clearer in the two assertions case.

Jason Punyon
+2  A: 

It Depends.

If you're doing something complex where having this be commutative is a critical function and isnt a no-brainer, then having the tests granular enough to reflect that makes sense - it allows you to isolate problems much quicker.

In lots of cases, this will be overkill. A test has to have a point.

Saying that doesnt mean that you should shoe-horn in as many asserts as possible - that would be too far in the other direction.

Bottom line is there is not and should not be an absolute rule for this. But the general point is to keep tests

  • Short
  • Useful in isolating issues
  • Useful in documenting behaviour
Ruben Bartelink
+1 ... 'It Depends.'
tanascius
+1  A: 

Both of your asserts test the same thing. That one object of a type is equal to another object of the same type. The Equals code doesn't have any way of telling which local variables it's being invoked on and which are parameters. I think it would suffice to have a single assert that says that any object of a type is equal to any other object of that type. If that is true, then commutativity holds.

tvanfosson
@tvanfosson: Depends on how Something.Equals is implemented, doesnt it?
Ruben Bartelink
How would you implement it so that you could pick any arbitrary element of a type and have it be equal to any other arbitrary element of the type and not be able to reverse those choices?
tvanfosson
It would be hard to mess up for normal simple types, but possible. The point is if you're testing the impl of an Equals method you've written, one of the properties it needs is to be commutative. hence you might want to cover that in your test?
Ruben Bartelink
If this happens then it seems to me that you're choosing something other than the simplest thing possible to pass the test or ignoring the semantics of the method deliberately.
tvanfosson
You last point makes sense. I'm just saying that a core part of whether an Equals method is correct is that it is commutative. In general whether it achieves that is not in doubt. Where there is any doubt, one might be testing just that aspect of the Equals implementation's functionality. If that's the purpose of the test, then you absolutely should have these two Assert.Equal calls (and probably put IsCommutative in the test name to reflect that fact. Or extract both assertions into an Assertion Method to make it really clear.
Ruben Bartelink