Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java testing: accelerate time to test timeouts?

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!

like image 335
luca Avatar asked May 12 '11 20:05

luca


People also ask

Does test Have timeout parameter?

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.

What does @test timeout 1000 annotation does in JUnit framework?

Annotations for Junit testing @Test(timeout=1000) annotation specifies that method will be failed if it takes longer than 1000 milliseconds (1 second).

How will you set the timeout in test cases?

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.


3 Answers

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.

like image 115
unholysampler Avatar answered Oct 13 '22 23:10

unholysampler


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;
// ...
like image 28
aioobe Avatar answered Oct 13 '22 21:10

aioobe


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)

like image 1
ratchet freak Avatar answered Oct 13 '22 23:10

ratchet freak