I like repeatable tests. The #1 benefit of repeatable tests is that they’re repeatable. This also means they’re less vulnerable to data changes (e.g. this test depends on this product record remaining unchanged) and don’t pollute your environment. There are two ways that I think you can make your tests repeatable, and I think both of them are equally valid, and each should be used in their appropriate time:
- Creating and tearing down fixtures
- Using some sort of mocking framework to force a repeatable result from an up-stream dependency that is not what you’re trying to test
Test::MockModule is a module I was introduced to in 2005, and since then I’ve used it quite a bit. The cool thing about this module is that if you need a function you depend on to return a consistent result when it normally might not (or would be guaranteed not to), you can kinda force it to. Take date math for instance. If you have been programming professionally for more than four years it is likely that you’ve encountered a leap year bug. Leap year bugs are annoying things which happen only on Feb 29th once every four years on the Gregorian calendar. They usually are difficult to test or anticipate all other days of the preceding and following four years. For this reason, mocking your date routine in your test could be very valuable.
You see how I mock
DateTime::now() to return Feb 1st, 2012 (a leap year). Then my function
advance_n_weeks_from_now() uses that value to add an interval to that value. First I test the value returned by
DateTime->now(), and then I test the value returned after adding five weeks.
Any test coverage is almost always better than no test coverage. Above that, repeatable test coverage is even better.
Test::MockModule gives you a very valuable tool for unit tests.
Test::MockModule would probably also be useful in larger units and integration test pieces as well. As with all testing, you should make sure you have a well-defined test plan, and you should build your test to the plan.