Test Utility Classes
When you start to write a substantial number of unit tests, you may discover that your tests have quite a bit in common. For instance, if you have a CreditCard class, you may have a block of code like this in each of your tests:
Assert.AreEqual( expectedCard.Number, actualCard.Number );
Assert.AreEqual( expectedCard.FirstName, actualCard.FirstName );
Assert.AreEqual( expectedCard.MiddleName, actualCard.MiddleName );
Assert.AreEqual( expectedCard.LastName, actualCard.LastName );
Assert.AreEqual( expectedCard.ExpMonth, actualCard.ExpMonth );
Assert.AreEqual( expectedCard.ExpYear, actualCard.ExpYear );
Of course, it won't be exactly the same in each test, and that just amplifies the problem. What happens when you want to add a variable to CreditCard? Copy, paste, paste, paste... and inevitably, miss one. One way to manage this complexity is to implement a custom Equals() method in your class. With that in place, you can collapse the previous code into this:
Assert.AreEqual( expectedCard, actualCard );
Sure enough, this reduces the amount of code in your unit tests and makes them less error-prone. However, if the equality test fails, you will know that one of the credit card's values is incorrect, but you won't know which. You can probably figure that out with a little debugging, but I prefer tests to be more explicit when they fail. So to deal with this, I'll typically create a test utility class for each class that looks something like this:
public class CreditCardUtil
{
public static void AssertAreEqual( CreditCard expected, CreditCard actual )
{
Assert.AreEqual( expected.Number, actual.Number );
Assert.AreEqual( expected.FirstName, actual.FirstName );
Assert.AreEqual( expected.MiddleName, actual.MiddleName );
Assert.AreEqual( expected.LastName, actual.LastName );
Assert.AreEqual( expected.ExpMonth, actual.ExpMonth );
Assert.AreEqual( expected.ExpYear, actual.ExpYear );
}
}
This way, the unit test code is just as simple, but you get meaningful error messages when the test fails. This pattern is useful when you're working on a TDD project with a group, because each person on the team will know where to look if they need a particular bit of functionality. Looking for a method that will compare two Invoices? Try InvoiceUtil.AssertAreEqual. Not there? Write it.
You may want to extend these utility classes to do other useful things, such as:
- Instance an object that is initialized with unique properties (useful for comparison)
- Perform CRUD database operations
- Setup all of the object's dependencies
- Define useful constants, file paths, etc. specific to the object
- Find a similar test
- Copy it
- Change it a little
- Repeat
No comments:
Post a Comment