工厂注解的执行顺序与我们配置实例的顺序不同

Factory annotation does not execute in the same order we configure the instances

我尝试使用@Factory 来运行 与多个实例相同Class。请注意,我是 TestNG 的初学者。

例如:

@Factory 的实现:

public class MainFactoryClass{
@Factory
public Object[] mainFactory() {

    Object[] data = new Object[3];

    data[0] = new MainImpClass(9);

    data[1] = new MainImpClass(10);

    data[2] = new MainImpClass(11);

    return data;
}
}

主要class:

public class MainImpClass {

int a;

public MainImpClass(int a) {
    this.a = a;
}


@Test
public void getValue1() {   

    System.out.println("Value from getValue1: " + a);

}

@Test
public void getValue2() {

    System.out.println("Value from getValue2: " + a);

}

@Test
public void getValue3() {

    System.out.println("Value from getValue3: " + a);

}

}

实际:

Value from getValue1: 9
Value from getValue2: 9
Value from getValue3: 9
Value from getValue1: 11
Value from getValue2: 11
Value from getValue3: 11
Value from getValue1: 10
Value from getValue2: 10
Value from getValue3: 10

testng.xml:

  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
  <suite name="Factory Suite">
  <test thread-count="5" name=" Factory Test" group-by- 
  instances="true">
  <classes>
  <class name="com.trial.MainFactoryClass"/>
  </classes>
  </test> <!-- Test -->
  </suite> <!-- Suite -->

已更新 - 实施 IMethodInterceptor:

 @Override
 public List<IMethodInstance> intercept(List<IMethodInstance> list, 
 ITestContext iTestContext) {

    Map<Integer, IMethodInstance> orders = new TreeMap<>(); // 
  Ordered MAP
    
    for (IMethodInstance instance : list) {
        MainImpClass testData = (MainImpClass) 
    instance.getInstance();
        orders.put(Integer.valueOf(testData.getA()), instance);

        
    }
    
    List<IMethodInstance> orderList = new 
    ArrayList<IMethodInstance>(list.size());
    
    
    for (Integer order : orders.keySet()) { // rearrange
        IMethodInstance test = orders.get(order);
        orderList.add(test);

    }
            return orderList; // TestNG will execute in the order  
    return List

    }

当我尝试 运行 它作为 TestNG 时,结果与我们从工厂传递的顺序不同。我们如何确保输出与我们传递的值相同?

如果没有定义其他顺序选项,测试方法按其

排序

<test-method-instance> name + <test-class-instance>.toString()

由于test-class.toString()总是有一些随机部分,如MainImpClass@28a0fd6c,默认的执行顺序是偶然的。

简化执行顺序的最简单方法是覆盖 test-class toString() 方法,例如:

@Override
public String toString() {
    return "MainImpClass" + a;
}

但这并没有回答您关于如何按照工厂提供的订单进行测试的问题。

如何保持Factory-defined订单

注意:这不是通用解决方案,仅适用于这个简单的上下文。

测试Class

添加了在 toString() 中引用的私有 order 变量。

public class MainImpClass {

    int a;

    private int order = 0;

    public MainImpClass(int a) {
        this.a = a;
    }

    @Override
    public String toString() {
        return "MainImpClass" + order;
    }

    void setOrder(int order) {
        this.order = order;
    }

    // ... rest of class

工厂Class

添加了 groupByOrder 方法,该方法根据数组中出现的 class 次设置顺序。

public class MainFactoryClass {
    @Factory
    public Object[] mainFactory() {

        Object[] data = new Object[3];

        data[0] = new MainImpClass(9);

        data[1] = new MainImpClass(10);

        data[2] = new MainImpClass(11);

        return groupByOrder(data);
    }

    private static Object[] groupByOrder(Object[] data) {
        for (int i = 0; i < data.length; i++) {
            ((MainImpClass) data[i]).setOrder(i);
        }
        return data;
    }
}

输出

Value from getValue1: 9
Value from getValue1: 10
Value from getValue1: 11
Value from getValue2: 9
Value from getValue2: 10
Value from getValue2: 11
Value from getValue3: 9
Value from getValue3: 10
Value from getValue3: 11

在 testng.xml

中应用 group-by-instances="true" 的输出
Value from getValue1: 9
Value from getValue2: 9
Value from getValue3: 9
Value from getValue1: 10
Value from getValue2: 10
Value from getValue3: 10
Value from getValue1: 11
Value from getValue2: 11
Value from getValue3: 11

如何改进

一些更通用的解决方案可能会使用 IMethodInterceptor TestNG 侦听器来实现。

class TestsOrderInterceptor implements IMethodInterceptor {

    @Override
    List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
        // sort by some rule
    }
}

并应用监听器

@Listeners(TestsOrderInterceptor.class)
public class MainFactoryClass {

或在XML套件中

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="factory-tests">
    <listeners>
        <listener class-name="TestsOrderInterceptor"/>
    </listeners>
    ...