tags:

views:

119

answers:

2

... not knowing if 'mock' is the right word.

Anyway, I have an inherited code-base that I'm trying to write some tests for that are time-based. Trying not to be too vague, the code is related to looking at the history of an item and determining if that item has now based a time threshold.

At some point I also need to test adding something to that history and checking that the threshold is now changed (and, obviously, correct).

The problem that I'm hitting is that part of the code I'm testing is using calls to time() and so I'm finding it really hard to know exactly what the threshold time should be, based on the fact that I'm not quite sure exactly when that time() function is going to be called.

So my question is basically this: is there some way for me to 'override' the time() call, or somehow 'mock out' the time, such that my tests are working in a 'known time'?

Or do I just have to accept the fact that I'm going to have to do something in the code that I'm testing, to somehow allow me to force it to use a particular time if need be?

Either way, are there any 'common practices' for developing time-sensitive functionality that is test friendly?

Edit: Part of my problem, too, is the fact that the time that things occurred in history affect the threshold. Here's an example of part of my problem...

Imagine you have a banana and you're trying to work out when it needs to be eaten by. Let's say that it will expire within 3 days, unless it was sprayed with some chemical, in which case we add 4 days to the expiry, from the time the spray was applied. Then, we can add another 3 months to it by freezing it, but if it's been frozen then we only have 1 day to use it after it thaws.

All of these rules are dictated by historical timings. I agree that I could use the Dominik's suggestion of testing within a few seconds, but what of my historical data? Should I just 'create' that on the fly?

As you may or may not be able to tell, I'm still trying to get a hang of all of this 'testing' concept ;)

+2  A: 

Personally, I keep using time() in the tested functions/methods. In your test code, just make sure to not test for equality with time(), but simply for a time difference of less than 1 or 2 (depending on how much time the function takes to execute)

Dominik
At the moment it looks like that's the way I'll have to go. I've added an 'example' to my problem, too, in case that helps. Thanks.
Narcissus
I saw your example. Again, personally, for this kind of tests I use the phpunit setup method to prepare the 'correct' historical data (for example inside the database)
Dominik
+1  A: 

Simplest solution would be to override PHP time() function and replace it with your own version. However, you cannot replace built-in PHP functions easily (see here).

Short of that, the only way is to abstract time() call to some class/function of your own that would return the time you need for testing.

Alternatively, you could run the test system (operating system) in a virtual machine and change the time of the entire virtual computer.

Milan Babuškov
Thanks Milan: while I agree that running in a VM would be an option to 'force' the time, I think I'd still have to account for the 'runtime variables' and so still end up doing what Dominik suggested. Interesting idea, though, thanks.
Narcissus