I have an app that manages turns in a game, it's fairly complex and it has a lot of timers that generate timeouts.. since they interoperate a lot it's difficult to be sure everything's working right (and keeps working right).
I'd like to test it, but certain timeouts are of a few minutes, to test it completely it'd take at least one hour!!
Is there any way to fake an accelerated time for the timers? Or should I just scale all the timeouts proportionally down, test them, and scale them up again each time?
thanks!
If a test case takes more time than the specified number of milliseconds, then JUnit will automatically mark it as failed. The timeout parameter is used along with @Test annotation.
Annotations for Junit testing @Test(timeout=1000) annotation specifies that method will be failed if it takes longer than 1000 milliseconds (1 second).
To specify the timeout period of a certain test case, “timeout” attribute is mentioned on the annotation @Test . Note that the timeout time is specified in milliseconds. In the above test, execution will be timed out after 500ms with the below message.
A way to do this would be to make your own interface that provides a thin wrapper around Timer
. You then program towards the interface everywhere in your code. After that, you make two implementations of the interface. The first is the expected implementation that connects to a real Timer
object like you have currently. The other is one that you can use for testing. In this implementation you mock the functionality of a Timer
, but you have full control of how the events are triggered and how long they take. You could scale the duration as suggested by @aioobe or you could make a backing queue that could rapidly fire events so that there is no wasted time.
The point is that you don't have to make changes to the real code and use Dependency Injection to make changes needed for testing.
There is to my knowledge no way to do a global scaling of the speed of the Java Timers. (Assuming they rely on the System.currentTimeMillis
method, you could perhaps try to add your own bootclasspath and override this implementation with something different, but this is tricky business for sure (if it's even possible).)
I suggest you add a TIME_SCALING
factor in front of periods and frequencies used for debugging purposes.
// ...
long period = (long) (someValue / TIME_SCALING);
// ...
// ...
double frequency = someValue * TIME_SCALING;
// ...
relying on timer ticks to happen on the right time is prone to difficult to trace and rare bugs
I'd suggest using locks, barriers, semaphores, ect. to guarantee happens-before relations on everything; this requires more interaction between classes but is more bullet proof (and allows the program to run faster in testing with only one timer needed if it goes way too fast)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With