如何使JUnit测试以随机顺序运行?

93ze6v8z  于 2023-01-26  发布在  其他
关注(0)|答案(7)|浏览(178)

我有经典的测试结构,我有一个不同套件的测试套件,如数据库测试,单元测试等。有时这些套件包含其他套件,如慢速数据库测试,快速数据库测试等。
我想要的是随机化测试的运行顺序,这样我就可以确保它们彼此不依赖。随机化应该在每一个级别上进行,就像套件应该重排测试类的顺序,而测试类应该重排测试方法的顺序一样。
如果可以在Eclipse中实现这一点,那将是最好的。

rpppsulh

rpppsulh1#

你确实有一个Sortable,但我不知道你会如何使用它。
您可以扩展BlockJUnit4ClassRunner并让computeTestMethods()返回super.computeTestMethods()的随机化副本,然后使用@RunWith将其设置为要使用的runner。
例如:

package com.stackoverflow.mlk;

import java.util.Collections;

import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;

public class RandomBlockJUnit4ClassRunner extends BlockJUnit4ClassRunner {

    public RandomBlockJUnit4ClassRunner(Class<?> klass)
            throws InitializationError {
        super(klass);
    }

    protected java.util.List<org.junit.runners.model.FrameworkMethod> computeTestMethods() {
        java.util.List<org.junit.runners.model.FrameworkMethod> methods = super.computeTestMethods();
        Collections.shuffle(methods);
        return methods;
    }

}

然后

@RunWith(com.stackoverflow.mlk.RandomBlockJUnit4ClassRunner.class)
public class RandomOrder {
    @Test
    public void one() {
    }

    @Test
    public void two() {
    }

    @Test
    public void three() {
    }
}
8ehkhllq

8ehkhllq2#

https://github.com/KentBeck/junit/pull/386引入了一些订单,但没有RANDOM,可能你并不真的想要这个;测试应该确定性地运行。2如果你需要验证不同的测试排列仍然通过,要么测试所有排列;或者,如果这样做太慢,那么可以引入一个由环境变量或类似变量确定的“随机”种子进行混洗,以便可以重现任何失败。http://hg.netbeans.org/main/file/66d9fb12e98f/nbjunit/src/org/netbeans/junit/MethodOrder.java给出了一个针对JUnit 3执行此操作的示例。

uqjltbpv

uqjltbpv3#

一般来说,您需要做的是编写自己的测试运行程序,并在测试运行程序类中聚合方法并随机运行每个测试(确保不运行两次测试)。
在此处阅读有关测试框架以及如何编写自己的测试运行程序的详细信息:http://www.ddj.com/architect/184415674

6qqygrtg

6qqygrtg4#

在JUnit 4.13中,要以随机顺序运行测试类中的测试,请编写一个小的helper类:

import org.junit.runner.manipulation.Ordering;

import java.util.Random;

public class RandomOrder implements Ordering.Factory {
    @Override
    public Ordering create(Ordering.Context context) {
        long seed = new Random().nextLong();
        System.out.println("RandomOrder: seed = " + seed);
        return Ordering.shuffledBy(new Random(seed));
    }
}

然后,使用以下内容注解测试类:

@OrderWith(RandomOrder.class)

这样,这个类的测试方法就以随机的顺序运行,另外,如果它们意外地失败了,你知道随机种子会完全按照这个顺序重复。
我不知道如何为整个项目或测试套件配置这个。

4c8rllxm

4c8rllxm5#

我会确保他们不会相互依赖
你应该确保不依赖于随机执行顺序的情况是这样的。是什么让你担心依赖关系可能存在呢?

toe95027

toe950276#

This issue is open on JUnit GitHub,并指出2个独立问题:

  • 取决于执行顺序的测试;
  • 不可重复测试。
    考虑从根本上解决问题,而不是尝试使用框架来完成工作。使用setUp和tearDown方法来保证隔离,并在最小的级别进行测试。
k2fxgqgv

k2fxgqgv7#

以下是GradleJUnit 5.8.0的解决方案
步骤1:确保您具有最新的JUnit版本依赖项。
步骤2:在build.gradle测试部分下定义所需的属性

test {  
    useJUnitPlatform()
    systemProperties([
         //Random in method level
        'junit.jupiter.testmethod.order.default': 'org.junit.jupiter.api.MethodOrderer$Random', 
         // Random in class level
        'junit.jupiter.testclass.order.default' : 'org.junit.jupiter.api.ClassOrderer$Random',
        // Log configuration to see the seed
        'java.util.logging.config.file' : file('src/test/resources/logging.properties')
    ])
    //To print the JUnit logs in console
    testLogging {
        events "passed", "skipped", "failed", "standardOut", "standardError"
    }
}

步骤3:在src/test/resources下定义logging.properties

.level=CONFIG
java.util.logging.ConsoleHandler.level=CONFIG
org.junit.jupiter.api.ClassOrderer$Random.handlers=java.util.logging.ConsoleHandler
org.junit.jupiter.api.MethodOrderer$Random.handlers=java.util.logging.ConsoleHandler

步骤4:运行测试。gradlew clean test
您可以在控制台中看到用于随机测试的种子

CONFIG: ClassOrderer.Random default seed: 65423695211256721
CONFIG: MethodOrderer.Random default seed: 6542369521653287

如果是片状测试,您可以通过配置JUnit测试失败的相同种子来重现它

systemProperties([
'junit.jupiter.execution.class.order.random.seed' : '65423695211256721'
'junit.jupiter.execution.order.random.seed'       : '6542369521653287'
])

参考文献:how-to-randomize-tests-in-junitRandom

相关问题