Test Overrides Now

A typical UnitTest establishes some known initial conditions (by creating objects with known values), executes a method with known parameters, and checks whether return values and side effects match expectations. But what happens when the method uses the system date and time?

Some Examples:

One would like to control the system date and time during testing to test with a known time (or more typically several known times). However, each method that needs the current time executes system.timeNow (names vary with language). This will to DoTheSimplestThingThatCouldPossiblyWork by letting the system code do it OnceAndOnlyOnce, but allows no control over the value of now.

(Also see the VirtualClock test pattern.)

Some ways that the TestOverridesNow are ...


Objection: Having all your code call one "current time" function that you write does not violate OnceAndOnlyOnce, as the system's "current time" function does not implement the required "override the clock" testing functionality. So, implement a "system.localTimeNow" that returns a certain preset time in certain testing situations, or otherwise calls system.timeNow.


Note that the answers will change if the input (i.e. date) changes. Therefore don't change the input. Therefore don't override now. Have a method accountsOverdueOn: aDate and test that on a known date, thusly:

 accountsOverdueOn: aDate
^accounts select: [ :each | each overdueOn: aDate]

accountsOverdueToday ^self accountsOverdueOn: Date today

The need to test accountsOverdueToday is, um, limited.


Tests that work with dates (and code in general) should almost never reference "now". Exceptions:


From: TestPrintedOutput

On the contrary. In most cases, to test with known values, the input dates must in fact NOT change.

Can you give an example of this?


Why not just pass in the test date as a parameter rather than getting the system date internally? This not only makes the routine easier to test but makes for a more general method as well.

If one must leave the system date internal to the method, then test by varying one's input date. One can test with System Date - 1 day, System Date, System Date + 1 day, etc.


Or change the system clock. What, you run tests as a limited user? HaHaOnlySerious


Two words: MOCK OBJECTS. That's what they were designed for. --SamuelFalvo?

Yes, MockObjects are your friends.


CategoryTesting


EditText of this page (last edited April 4, 2008) or FindPage with title or text search