The little test that could … not
Consider the following code:
Run this test today and it will pass, but it has one obvious flaw. Can you spot it?
The test will fail on the same day once a year, on the person’s birthday.
“But Runar”, you say, “this only happens once a year and the test can be corrected in a couple of minutes.”
That is true, but remember that this test does not live alone. In any non trivial product where the development organization has practiced some kind of automated testing, it will be one of 10,000s. In a product of with 50,000 tests, 5 tests will fail daily if the failure rate is as low as 0.01%. An unacceptable waste of time.
A unit test is defined in The Art of Unit Testing as a test that:
- Is automated and repeatable.
- Is easy to implement.
- Remains for future use once it’s written.
- Is runnable by everyone.
- Is run at the push of a button.
- Runs quickly.
The test is automated, but it is not a proper unit test given the criteria above. The persons age is dependent on the current date, and thus its result will vary.
Luckily, making the test more robust is easy using the D in the SOLID principles: Dependency Inversion. Extract the needed date and time operations behind an interface, make the dependency on that interface explicit and inject the dependency where it is needed.
The example below shows a suggestion for such an interface, IClock. Using a stub, the test will always pass regardless of the current date. I’ve used a manual stub here, but it can just easily be created using a framework like Moq.
A unit test should never depend on externalities that you do not control. Time is a prime example, and it should be encapsulated in a suitable abstraction. The IClock-interface is a proposal, another solution is using a mature time-framework such as Noda Time where this abstraction is already available.
The code for this post can be found on Github.