Fog Creek Software
Discussion Board




Testing Time sensitive applications

How do you test an application with behavior dependent on the date?  Either absolute dates like the beginning of a quarter or relative dates like 60 days after some event.

Changing your machine clock used to be a good solution but now I understand Active directory may not let a machine with an incorrect date connect to other systems. And even if the local machine's clock is changed that will not affect the database server or other systems.

What I would like to do is to add some records, somehow move the time forward to the next event date test that process and go to the next event date etc.

The approach I use now is to tweak the database records to so the relative date processing will run, but that does not handle all the cases.

john
Wednesday, April 14, 2004

Since 60 days is like 5184000 seconds, how about:

sleep( 5184000 );
result = test(blah);
sleep( - 5184000 );
print result;

Matthew Lock
Wednesday, April 14, 2004

Maybe create a wrapper function to obtain the time, like "GetTime()" or whatever.  When you're in release mode, it returns the "correct" system time.  When you're in debug mode, it returns the modified time for testing purposes.

I'm actually dealing with this right now, and I think that's how I'm going to do it.

I'd be interested to hear anybody else's take on the problem...

John Rose
Wednesday, April 14, 2004

I've found that the easiest way to test this kind of thing is to create an interface for a 'time provider' and explicitly pass this provider to the parts of the application that require it. Then, when you want to test things, you can simply (!) pass in a provider that says whatever date you want rather than the actual date... This works best for unit testing...

I blogged about this kind of thing here: http://www.lenholgate.com/archives/000127.html

Len Holgate
Wednesday, April 14, 2004

What Len is refferring to I believe is known as a mock object (http://www.mockobjects.com/wiki/).  This sounds like exactly what you need.  During testing, you would replace your real object with your testing object with preset values.  Then all other objects within your code would work as if it were getting the real data that you are trying to simulate.

Seeker
Wednesday, April 14, 2004

Seeker,

Correct ;)

Len Holgate
Wednesday, April 14, 2004

The Mock Object approach sounds good thanks. 

Extending that to the database you would need to create your own date function instead of using the system call.

john
Wednesday, April 14, 2004

Or else always supply dates as parameters to your SQL.  I had to do this recently on a Sybase->Oracle migration project.  To do testing, we needed to be able to test the exisiting app "as of" various dates and times on both systems, and because the reports include various date arithmetic, it was necessary to convert all uses of GETDATE() et al with passed-in parameters, and hack up a mockable function to get the "as of" date and time when running in test mode.

Luckily, we already had a single point for getting the current time within the application, because we wanted to have a single "transaction time" for all dates recorded by the transaction.  In other words, if a transaction takes a second or two, we didn't want some of the dates recorded in the DB to be different from others.

So, centralizing a time function and tying it to your transaction scope, and not using *any* other source for the current time, even in SQL, is a good pattern to follow for both testability and transaction consistency.

Phillip J. Eby
Wednesday, April 14, 2004

*  Recent Topics

*  Fog Creek Home