CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Karl Seguin

.NET From Ottawa, Ontario - http://twitter.com/karlseguin/

The secret to unit testing: the unit

After spending time in some of my old code this weekend, I've come to the conclusion that developers new to unit testing are likely to bloat their tests.
Since your test has set up some type of state, it's very tempting to test the complete state, rather than the specific behaviour you're looking to validate.

For example, we might have a Save method who's interaction we want to test, so let's start off with a simple test:

[Test]
public void SavingANewUserCallsDataStore()
{
   //todo move to SetUp
   MockRepository mock = new MockRepository();
   IDataStore dataStore = mock.CreateMock<IDataStore>();

   User user = User.CreateNewUser();  
   Expect.Call(dataStore.SaveUser(user)).Returns(39);
   mock.ReplayAll();

   user.Save();
   //todo move to teardown
   mock.VerifyAll();
}

Great, the test does exactly what it says it will: it validates that our datastore's SaveUser method is called. While we're at it, why don't we make sure that calling user.Save() did a couple other things? So we add:

Assert.AreEqual(39, user.UserId);
Assert.AreEqual(UserStatus.Normal, user.Status);

The change might seem pretty useful, but we've actually taken a step back. Our test is now doing a lot more than it advertises, which not only makes it less useful as documentation, but also harder to maintain. If either of the two new behaviours we are testing (that the UserId gets set or that the status changes) change, our test will break.

What's worse is that these trivial extras have a tendency to get repeated over and over again, while at the same time never having a dedicated test for the specific behaviour (why bother, we've tested that the userId gets set in 4 other Save tests).

I've read once or twice that unit test should never have more than a single assert. I certainly don't agree with that as a rule, but I understand the spirit in which it was said. I've redoubled my efforts to focus on the specific unit while unit testing, and I'm already seeing the effort pay off. My tests are far more maintainble and understanble. That my friends is a recipe for success.



Comments

Peter Ritchie said:

Asserts: I would be suspect of anything that says one assert per test.  It depends on what you're testing for the most part.  I would expect at least one assert for each post condition.  Sure, you could say that each post condition should be it's own test; but if all the same inputs would be used for each of those tests, you're really just testing the same thing.

# July 20, 2007 9:40 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!

Our Sponsors