标记为运行太长的JUnit测试失败

Pio*_*aba 20 java junit maven

我想停下来并标记为失败太长时间运行junit测试(在Maven 3版本中执行).我知道有三种方法:

1)使用带有超时参数的Test注释:

@Test(timeout=100)
public void testWithTimeout() {
    ...
}
Run Code Online (Sandbox Code Playgroud)

2)使用规则注释:

@Rule
public Timeout globalTimeout = new Timeout(100);
Run Code Online (Sandbox Code Playgroud)

3)使用以下选项配置maven-surefire-plugin:

forkedProcessTimeoutInSeconds=1
reuseForks=false
Run Code Online (Sandbox Code Playgroud)

线索是1)和2)需要改变每个测试(当你有成千上万时它会受到伤害).3)解决方案是不可接受的,因为在许多模块中,首先测试开始测试所使用的上下文 - 测试性能将急剧下降.

你有任何其他想法如何实现吗?任何棘手的解决方案(不涉及修补JUnit :))?

Gon*_*n I 0

实际上,超时规则对类中的所有测试方法应用相同的超时。

如果您不想将其添加到每个 Test 类中,则可以在 Test 基类中定义一次。

对于不需要更改所有类的东西,您可以实现 Junit 自定义套件运行程序(请参阅第二个代码示例)

只是为了好玩,这个使用已弃用的 Thread.stop 方法的黑客解决方案怎么样?

Before 函数为每个测试启动一个观察线程,超时后会终止 Junit 测试线程。

如果测试完成,清理会杀死观察者线程。

适用于这个小演示,不确定这是否适用于生产规模。

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);
    }

}
Run Code Online (Sandbox Code Playgroud)

或者使用套件对多个测试类执行此操作:

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);


    }      
}
Run Code Online (Sandbox Code Playgroud)