This post originated from an RSS feed registered with .NET Buzz
by Roy Osherove.
Original Post: The role of helper frameworks in your tests
Feed Title: ISerializable
Feed URL: http://www.asp.net/err404.htm?aspxerrorpath=/rosherove/Rss.aspx
Feed Description: Roy Osherove's persistent thoughts
As you create tests for a system that gets bigger and bigger, so do the tests
become bigger and more complex. One of the problems that start to occur is that
you test code starts getting riddled with various object-creation code. For
example, you're testing a complex business object's state, to make it just right
for testing an exception that should be thrown. That sort of creation can take
many lines of code and might repeat itself in other tests too. This causes
several symptoms:
First, your tests are now much less readable than they should be. Tests
should be readble so they can serve as part of the overall API documentation
which can then be used by members of your team to familierize themselves with
your code.
Second, you're breaking one of the first rules of good code : "Don't repeat
yourself". Duplication in your tests is just as bad as duplication in your
prodcution code. In this case there's going to be lots of duplication in the
creation and state-setting of your to-be-tested business objects.
By refactoring, we can start removing this duplication into various helper
methods that will be laid down within our test fixture. However, this still has
the effect of making your test fixture do more than one thing (it's both a test
fixture and a helper class now). Additional refactoring eventually leads us to
create a helper class with specific helper methods (usually static) for the
business objects under test.
This "Pattern" of helper methods and factories for your unit tests is not
new. It's been called several names ("ObjectMother"
- PDF , for example) and eventually, most developers that implement unit
tests arrive at the same conculsion, one way or the other.
Assuming that most projects will have at least one such helper class, we can
and should begin to realize and think about our helper factories and classes for
testing as pure frameworks on which to build our tests. These frameworks can
later be used to run not only our developer tests, but our customer tests as
well (using FIT, for example). Given the "organic" nature in which an
agile software project usually grows, these frameworks are grown, and not
pre-designed. As such, we should pay special attention to them as they are
created and nurtured, and to make sure that once one has benn "born" we start
thinking of it as a service to out tests, and to future tests as well. For
example, there may be a good point in time where these factories and helpers
will need to become a separate assembly in our tests, so that it can be re-used
in other testing scenarios. We can also re-use these frameworks later adding
more generality to them and thus making them easier to use with customer tests.
These frameworks can be very small in small applications (one-two utility
classes) or very big on large ones (hierarchical, categorized and refactored
classes for each object type, test type and so on). One of the most important
things to keep in mind as you build such a framework is to re0use existing
methods to their smallest parts. That is, make your code inside those methods
repeat itself exactly once. The minute ou break this rule you're heading down a
path where future changes in your business objects might lead to big lengthy and
painful changes in your helpers. If you keep the DRY rule, you'll most likely
need to change very little creation code in order to support such changes. Even
the acto of callin "new" on an object should be repeated only once and
refactored into a method that will be re-used by all other helper methods. That
way if your object loses its default constructor, for example, you need only
change one simple method to factor the change into your helper
framework.