How to set timeout at runtime in JUnit Test Case - java

I am using JUnit v4 as a test framework. I wanted to know how to set timeout at runtime in Test Case?
I am using Parameterized test. In which I have a list of Scenario, which contains timeout value and some other fileds. Each of these Scenario may have different-2 timeouts.
The timeout parameter is not helping me to achieve this.
#Test(timeout = getTimeOut())
public void secureLoginWithLongUsername() {
// Test case goes here
}
private final long getTimeOut() {
// I am doing some processing here to calculate timeOut dynamically
long timeOut = scenario.getTimeOut();
return timeOut;
}
#Parameters
public static Collection<Scenario[]> getParameters() {
List<Scenario[]> scenarioList = new ArrayList<Scenario[]>();
Configuration config = new Configuration();
List<Scenario> scenarios = config.getScenarios();
for (Scenario scenario : scenarios) {
scenarioList.add(new Scenario[] { scenario });
}
return scenarioList;
}
public class Configuration {
private List<Scenario> scenarios;
//Some processing here
public List<Scenario> getScenarios() {
return scenarios;
}
}
public class Scenario {
private long timeOut;
private String name;
//Some more fields here
}
Please help me to fine out any alternative to set the timeout dynamically.

I think, you need to build it yourself, like:
private Timer timer;
#After
public void terminateTimeout() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
#Test
public void testTimeout() throws Exception {
setTimeout(1000);
// run test...
}
private void setTimeout(int duration) {
final Thread currentThread = Thread.currentThread();
timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
currentThread.interrupt();
}
}, duration);
}

Related

Stop running Java JUnit test method after predefined time without failing the test

I have a class that starts multiple threads which all run while(true) loops. Is it possible to have an Assert statements on the state of a test after it has run for a certain amount of time?
The Timeout functionality would work, if it didn't fail the test.
This is a contrived example to show what I'm trying to do. The test is at the bottom.
class RunProgram {
private DataClass dataClass = new DataClass();
private Thread1 thread1 = new Thread1(dataClass);
void startThis() {
ExecutorService pool = Executors.newFixedThreadPool(5);
try {
pool.execute(thread1);//Thread 1
//... more threads with while loops
runMainThread(dataClass);
} finally {
pool.shutdown();
}
}
void runMainThread(DataClass data1){
while(true){
dataClass.setInternalDataInt(20);
//do stuff
}
}
public Thread1 getThread1(){
return this.thread1;
}
}
class Thread1 implements Runnable{
private DataClass dataClass;
Thread1(DataClass dataClass){
this.dataClass = dataClass;
}
public void run() {
dataClass.setInternalDataInt(10);
while (true) {
//dostuff
}
}
public DataClass getDataClass(){
return dataClass;
}
public void setDataClass(DataClass dataClass){
this.dataClass = dataClass;
}
}
class DataClass {
private int internalDataInt;
public int getInternalDataInt(){
return this.internalDataInt;
}
public void setInternalDataInt(int internalDataInt){
this.internalDataInt = internalDataInt;
}
}
class Tests{
#Test
public void stateOfThread1() {
RunProgram runProgram = new RunProgram();
runProgram.startThis();
//Run above for 100 millisecond and then end
Assertions.assertEquals(runProgram.getThread1().getDataClass().getInternalDataInt(), 20);
}
}
Found what I was looking for.
Use a ScheduledExecutorService:
An ExecutorService that can schedule commands to run after a given
delay, or to execute periodically.
RunProgram runProgram = new RunProgram();
ScheduledExecutorService testExecutor = Executors.newScheduledThreadPool(1);
Future future = testExecutor.submit(runProgram);
Thread.sleep(500);
future.cancel(true);

How to timeout all tests in a class?

I have 1000+ test cases loaded from file and run within file.
Since the tests can take overly long I introduced I timeout for all of them:
#ClassRule
public static Timeout classTimeout = new Timeout(200);
This was working fine in Junit4, but now, once I migrated the test to Junit5, I can see no support for #ClassRule.
There's #Timeout annotation but it works per test method.
I couldn't find functionality like this provided by junit, so i came up with a somewhat naive implementation to fail every test when cumulative execution time exceeds a limit.
What is needed:
BeforeAllCallback.beforeAll()
Callback that is invoked once before all tests in the current container.
BeforeTestExecutionCallback.beforeTestExecution()
Callback that is invoked immediately before an individual test is executed but after any user-defined setup methods have been executed for that test.
AfterTestExecutionCallback.afterTestExecution()
Callback that is invoked immediately after an individual test has been executed but before any user-defined teardown methods have been executed for that test.
public class AllTestsTimeoutException implements BeforeAllCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback {
private final long maxElapsedTimeNanos;
private long start;
public AllTestsTimeoutException(long maxElapsedTimeNanos) {
this(maxElapsedTimeNanos, TimeUnit.NANOSECONDS);
}
public AllTestsTimeoutException(long value, TimeUnit timeUnit) {
this.maxElapsedTimeNanos = timeUnit.toNanos(value);
}
#Override
public void beforeAll(ExtensionContext context) throws Exception {
start = System.nanoTime();
}
#Override
public void beforeTestExecution(ExtensionContext context) throws Exception {
checkElapsedTimes(context, "Before check");
}
private void checkElapsedTimes(ExtensionContext context, String prefix) {
long elapsedNanos = System.nanoTime() - start;
System.out.println(prefix + " - " + context.getRequiredTestMethod().getName() + " - " + elapsedNanos);
if (context.getExecutionException().isEmpty() && elapsedNanos > maxElapsedTimeNanos) {
throw new RuntimeException("all tests time out");
}
}
#Override
public void afterTestExecution(ExtensionContext context) throws Exception {
checkElapsedTimes(context, "After check");
}
}
It needs some polishing, but it can serve as starting point to improve from.
Registration is as a public static field in the class with RegisterExtension.
public class TimeoutTests {
#RegisterExtension
public static AllTestsTimeoutException timeout = new AllTestsTimeoutException(25, TimeUnit.MILLISECONDS);
#Test
public void test1() {
//test stuff
}
#Test
public void test2() {
//test stuff
}
#Test
public void test3() {
//test stuff
}
}

Java 7 web service scheduler implementation suggestion

I know there are many frameworks for Scheduler as well as JDK's own Scheduler. I can't use any third party framework/API. The existing scheduler uses only Java API. It is as follows:-
public class Timer implements Runnable {
private Thread runner;
private int pause;
private Task task;
private boolean running;
public Timer(int pause, Task task) {
this.pause = pause;
this.task = task;
runner = new Thread(this, "Timer");
}
public void run() {
try {
while (running) {
task.run(); // long running task
synchronized (runner) {
runner.wait(pause);
}
}
} catch (InterruptedException ie) {
/* The user probably stopped the */
}
}
Interface and class:-
public interface Task {
void run();
}
public class TaskManager implements Task {
private static boolean firstRun = true;
private static Timer timer;
private static String lastRun;
public static void start(int interval) {
// stop any previous
if (timer != null) {
timer.stopTimer();
timer = null;
}
// Start a new one
TaskManager taskManager = new TaskManager ();
timer = new Timer(interval * 1000, taskManager );
timer.startTimer();
}
public void run() {
// long running code
}
public void setDelay(int p) {
pause = p;
}
public void startTimer() {
running = true;
runner.start();
}
public void stopTimer() {
running = false;
runner.interrupt();
}
}
From a servelet I call as:
private void startTaskManager() {
TaskManager.start(30);
}
My requirements that it will perform task in a thread in the run() method. There are many tasks that will be picked one after another from the database.
The above implementation has some issues. On the above implementation, it has own interface Task and implemented own Timer.
I think there is another better way to achieve this scheduler. Please suggest me.

libgdx - junit testing - how do I communicate with the Application thread?

I am trying to do junit testing on a libgdx game, and have found this thread to be very helpful: Unit-testing of libgdx-using classes
I have a test class similar to the following:
public class BoardTest {
private static Chess game;
private static HeadlessApplication app;
#BeforeClass
public static void testStartGame() {
game = new Chess();
final HeadlessApplicationConfiguration config = new HeadlessApplicationConfiguration();
config.renderInterval = 1f/60; // Likely want 1f/60 for 60 fps
app = new HeadlessApplication(game, config);
}
#Test
public void testSetUpBoard() {
final boolean isFalse = false;
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
//do stuff to game
fail(); //see if the test will fail or not
}
});
}
}
When I run this test class, it runs testSetUpBoard() and passes, instead of failing like it should. The reason for this, I believe, is because the executed code is in a separate thread as per Gdx.app.postRunnable(). Is there any way that I can communicate back to the junit thread, so that I can complete my tests like described?
You can wait for the thread to finish like this:
private boolean waitForThread = true;
#Test
public void testSetUpBoard() {
final boolean isFalse = false;
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
//do stuff to game
waitForThread = false;
}
});
while(waitForThread) {
try {
Thread.sleep(10);
} catch(Exception e ) {
}
}
// fail or pass...
fail(); //see if the test will fail or not
}

How to write unit test which creates new thread

I have following method for test:
public class classToTest{
#Autowired
private Alternator alternator;
public void methodToTest(){
Thread t = new Thread(new Runnable() {
public void run() {
while(true) {
if(alternator.get()) {
System.out.print("Hello");
alternator.set(false);
}
}
}
};
t.start()
}
}
I need to check that was invoked method
alternator.set(false);
How can I do it?
Instead of starting a thread directly, can you pass in an "Executor" instance?
For example...
public class ClassToTest{
#Autowired
private Alternator alternator;
#Autowired #Qualifier("myExecutor")
private java.util.concurrent.Executor executor;
public void methodToTest() {
Runnable runnable = new Runnable() {
public void run() {
while(true) {
if(alternator.get()) {
System.out.print("Hello");
alternator.set(false);
}
}
};
executor.execute(runnable);
}
}
Now you can test this easier...
public class ClassToTestTest {
...
#Before
public void setup() {
alternator = mock(Alternator.class);
executor = mock(Executor.class);
obj = new ClassToTest();
ReflectionTestUtils.setField(obj, "alternator", alternator);
ReflectionTestUtils.setField(obj, "executor", executor);
}
#Test
public void shouldStartRunnable() {
obj.methodToTest();
ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
verify(executor).execute(runnableCaptor.capture());
Runnable runnable = runnableCaptor.getValue();
// Now test your actual "runnable"...
when(alternator.get()).thenReturn(true);
runnable.run();
verify(alternator).set(false);
}
}
(Have not tried to compile this, so I apologise if there are any mistakes!!)
Though Bret's post of passing in an executor is very much recommended, you can use the timeout() mock verification setting to test for asynchronous conditions.
verify(alternator, timeout(500)).set(false);
Note that this will necessarily increase the flakiness of your test (i.e. the likelihood that the test fails when the code passes). With a sensible timeout value, that flakiness should be negligible, but if you're making this a part of your core test infrastructure you may consider refactoring to allow for synchronous execution in the test.

Categories