如何确保TestNG连续在测试类上运行方法而不是交错?

时间:2013-06-24 09:51:58

标签: testng

情况和问题

我有几个测试类,每个测试类都有几种测试方法。所有测试在后台使用相同的测试数据库。每个测试类初始化其数据库内容,然后在几种测试方法中测试内容。

当我单独进行每项测试时,它们都会通过。但是当我同时运行多个测试时(使用maven或我的IDE,IntelliJ),不同测试类的方法是交错运行的,例如。第一个类的数据库初始化在第一个类开始之后但在第一个类的所有测试方法都已运行之前运行,因此这些方法将失败(因为数据库已经包含第二个类的数据)。

我尝试过的一些事情,以及更多细节

最简单的解决方案是强制TestNG运行器连续运行类(即等待测试类的所有测试方法在运行另一个类的测试方法之前完成)。可以这样做吗?

我可以通过在我的套件中将每个类指定为单独的测试来实现这一点,但我不想这样做,因为这意味着每当我添加一个测试类时,我都必须向套件中添加一些内容。笨拙且容易出错。

简单地要求TestNG不并行化任何东西(例如,将线程数设置为1或禁用并行运行)在这里没有帮助,因为方法仍然以错误的顺序运行(尽管不是同时运行)。

一种选择是为每个测试类使用不同的数据库,但我没有看到一种简单的方法(使用JPA和Guice)。

我目前没有使用DBUnit,Unitils等;我不太了解这些工具,但我得到的印象是不能解决我的问题。

我正在使用JPA在每个测试类中初始化数据库(即创建实体对象并对其进行预定)。

7 个答案:

答案 0 :(得分:6)

即使在顺序模式下,TestNG也可以交错来自同一套件的测试方法。它保证了序列@BeforeClass - > @Test - > @AfterClass但它可以做类似的事情:

before class1
    test class1.method1
before class2
    test class2.method1
    test class1.method2
after class1
    test class2.method2
after class2

解决方案是强制每个类在不同的套件中(这些套件是按顺序执行的)。从版本2.16开始,maven surefire插件将每个类放在一个单独的套件中,以便解决问题。

另一方面,IDEA(甚至是最新的13个EAP)生成一个xml文件,其中包含同一套件中的所有类。希望IDEA也会效仿并解决这个问题。在使用数据库等共享资源时,交错测试是一种显而易见的方法。

答案 1 :(得分:2)

带来了类似的问题。我认为逐个实例=“真实”可能是一个解决方案。

答案 2 :(得分:1)

TestNG提供了几种并行策略。看起来methods对您的需求过于激进,但您是否看过classesinstances

答案 3 :(得分:0)

我写了一篇文章,讨论了在TestNG中对测试进行排序的一些方法:

http://ancient-marinator.blogspot.com/2013/05/on-testing-scheduling-your-tests.html

当然,最好的信息来源是在家:http://testng.org/doc/index.html

答案 4 :(得分:0)

使用method interceptors(=编写并启用自定义)来控制排序。

此外,每个类可能使用自己的数据库沙箱:将每个测试类包装到事务中可能会有所帮助。

为每个类设置表/ db的单独后缀甚至可以让你的测试方法并行运行(我猜前两个选项不会)。

答案 5 :(得分:0)

我不会在类级别使用dependsOnGroups,因为如果你所依赖的任何类中的任何测试方法都失败了,它根本不会运行你的类...这是使用'dependsOn的真正缺点'组(或方法)。我首先尝试在类级别设置@Test(group = thisClassName),然后在testng.xml文件中标识带有测试标记的类。然后控制类的顺序在xml中运行,作为这些测试的列表。我相信您可能还需要在xml中的下一个更高级别标记上设置PreserveOrder =“True”。我会避免使用dependsOn,除非你真的需要依赖,但不是为了控制顺序。希望这可以帮助。 -JR

答案 6 :(得分:0)

我们遇到了同样的问题,大多数人都认为这是由于使用dependsOn造成的,但我们的解决方案只是在某些测试的测试级别设置优先级。我设置了一个测试监听器来重新确定测试的优先级,以便它们以正确的顺序运行。这是基于saberduck的解决方案 https://github.com/cbeust/testng/issues/106

此解决方案将通过将测试优先级连接到类优先级来保留测试优先级。

package testng_Listeners;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import org.testng.IAnnotationTransformer;
import org.testng.Reporter;
import org.testng.annotations.ITestAnnotation;

//Listener to fix TestNG Interleaving issue. I had to re-write this as the original example I had did not allow for priority to be manually set on a test level.
public class RePrioritizingListener implements IAnnotationTransformer {

HashMap<Object, Integer> priorityMap = new HashMap<Object, Integer>();
Integer class_priorityCounter = 10000;
// The length of the final priority assigned to each method.
Integer max_testpriorityLength = 4;

@Override
public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {


// class of the test method.
Class<?> declaringClass = testMethod.getDeclaringClass();
// Current priority of the test assigned at the test method.
Integer test_priority = annotation.getPriority();
// Current class priority.
Integer current_ClassPriority = priorityMap.get(declaringClass);

if (current_ClassPriority == null) {
    current_ClassPriority = class_priorityCounter++;
    priorityMap.put(declaringClass, current_ClassPriority);
}

String concatenatedPriority = test_priority.toString();

// Adds 0's to start of this number.
while (concatenatedPriority.length() < max_testpriorityLength) {
    concatenatedPriority = "0" + concatenatedPriority;
}

// Concatenates our class counter to the test level priority (example
// for test with a priority of 1: 1000100001; same test class with a
// priority of 2: 1000100002; next class with a priority of 1. 1000200001)
concatenatedPriority = current_ClassPriority.toString() + concatenatedPriority;

//Sets the new priority to the test method.
annotation.setPriority(Integer.parseInt(concatenatedPriority));

String printText = testMethod.getName() + " Priority = " + concatenatedPriority;
Reporter.log(printText);
System.out.println(printText);

}
}

此外,您还需要将监听器添加到testng.xml

<suite name="Suite" configfailurepolicy="continue" >
<listeners>
<listener class-name="testng_Listeners.RePrioritizingListener"></listener>
</listeners>