Dates are annoying in automated tests. You’ll inevitably have all kinds of business rules like “if the case is unresolved and older than 15 days send a nasty email to the owner of the case to tell them to get off their duff and fix the problem already.” Those kinds of rules really deserve automated acceptance / regression tests, but….
- Automated tests are only useful when you can start from known inputs / test data
- Your business rules work by comparing “today’s date” against the dates of the data using the system clock one way or another
- The system clock is obviously going to be different tomorrow
I think you’ve got two main choices to make your automated tests with date rules:
- Don’t access DateTime.Now or DateTime.Today directly in your code. Use some sort of ISystemClock service that you can mock inside your tests. Jimmy Bogard describes that strategy here.
- Go ahead and access DateTime directly in your code, but use a mechanism in your test data setup that “corrects” your test data to make dates relative to the system clock.
The problem with approach #1 is that a.) you have to remember not to access DateTime.Now/Today directly, and b.) The tests aren’t as readable to the business partners, testers, and even you. If you rely on absolute dates with some sort of mechanism that locks in “Today is 10/26/2008,” you have to look at each and every date in the test data and compare it to this arbitrary date that defines “today.”
For readability sake, I like to define test data using “TODAY”, “TODAY+#”, or “TODAY-#” to reflect relative dates. The big advantage being that this type of date formatting clearly says “today’s date” or “31 days ago” or “2 days from now” without having to compare an absolute date against an arbitrary “now” time.
Using the StoryTeller trunk (as of my last checkin. I’ve used this strategy with Fit/FitNesse in the past as well)
<!-- Today's date -->
<somegrammar thedate="TODAY" />
<!-- 4 days ago -->
<somegrammar thedate="TODAY-4" />
<!-- 3 days from today -->
<somegrammar thedate="TODAY+3" />