Actually The Timeout Rule applies the same timeout to all test methods in a class.
If you don't want to add it to every Test class, you can define it once in a Test base class.
For something that doesn't require a change to all classes, you could implement a Junit custom suite runner ( See second code example )
Just for fun how about this hacky solution using the deprecated Thread.stop method?
Before function starts a watcher thread for every test, which after a timeout kills the Junit test thread.
If the test completes, cleanup kills the watcher thread.
Works for this little demo, not sure if this would work on production scale.
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
// You could also make this a base class for test classes
public class TimeoutTest {
Thread watcherThread ;
Thread junitTestThread;
final static int testTimeout = 2000;
@Before
public void myInit()
{
junitTestThread = Thread.currentThread();
watcherThread = new Thread()
{
@Override
public void run()
{
try {
Thread.sleep(testTimeout);
junitTestThread.stop();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
watcherThread.start();
}
@After
public void myCleanup() throws InterruptedException
{
watcherThread.stop();
}
@Test
public void testPassingFastTest() throws InterruptedException {
Thread.sleep(1000);
}
@Test
public void testFailingSlowTest() throws InterruptedException {
Thread.sleep(3000);
}
}
Or to do this for several test classes using a suite:
import java.util.Arrays;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerBuilder;
@RunWith(AllTests.class)
public class AllTests extends Suite{
Thread watcherThread ;
Thread junitTestThread;
final static int testTimeout = 70;
public AllTests(final Class<?> clazz) throws InitializationError {
super(clazz, findClasses());
}
private static Class<?>[] findClasses() {
// You could write code here to get the list of all test classes from specific directories
return new Class<?>[] {TimeoutTest.class,TimeoutTest2.class};
}
@Override
public void run(final RunNotifier notifier) {
notifier.addListener(new RunListener() {
@Override
public void testStarted(final Description description) {
System.out.println("Before test " + description.getDisplayName());
junitTestThread = Thread.currentThread();
watcherThread = new Thread()
{
@Override
public void run()
{
try {
Thread.sleep(testTimeout);
junitTestThread.stop();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
watcherThread.start();
}
@Override
public void testFinished(final Description description) {
System.out.println("After test " + description.getDisplayName());
watcherThread.stop();
}
}
);
super.run(notifier);
}
}