【问题标题】:Only the last @Test is being executed when using IMethodInterceptor as Listener in TestNG在 TestNG 中使用 IMethodInterceptor 作为侦听器时,仅执行最后一个 @Test
【发布时间】:2022-01-28 06:57:34
【问题描述】:

我正在尝试使用@Factory 创建一个类的多个实例,并按照我们使用IMethodInterceptor 侦听器传递的相同顺序打印值:

public class MainFactoryClass implements IMethodInterceptor {

@Factory
public Object[] mainFactory() {

    Object[] data = new Object[6];
    data[0] = new MainImpClass(9);
    data[1] = new MainImpClass(10);
    data[2] = new MainImpClass(11);
    data[3] = new MainImpClass(12);
    data[4] = new MainImpClass(13);
    data[5] = new MainImpClass(14);
    return data;
}

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

    Map<Integer, IMethodInstance> orders = new TreeMap<>();

    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()) {
        IMethodInstance test = orders.get(order);
        orderList.add(test);        
    }
    return orderList;
}

}

如果我有 5 个 @Test 方法来打印类中的值,它只考虑最后一个 @Test 方法并打印值。我究竟做错了什么?。即getValue1, getValue2, getValue3, getValue4 未运行。

尝试使用prioritydependsOnMethods。代码如下:

@Listeners({ MainFactoryClass.class })

public class MainImpClass {
int a;

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

public int getA() {
    return a;
}

@Test(priority = 0)
public void getValue1() {
    System.out.println("Value from getValue1: " + a);
}

@Test(priority = 1)
public void getValue2() {
    System.out.println("Value from getValue2: " + a);
}

@Test(priority = 2)
public void getValue3() {
    System.out.println("Value from getValue3: " + a);
}

@Test(priority = 3)
public void getValue4() {
    System.out.println("Value from getValue4: " + a);
}

@Test(priority = 4)
public void getValue5() {
    System.out.println("Value from getValue5: " + a);
}

}

输出按我们创建实例的顺序排列,但仅从最后一个@Test开始。

Value from getValue5: 9
Value from getValue5: 10
Value from getValue5: 11
Value from getValue5: 12
Value from getValue5: 13
Value from getValue5: 14

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

【问题讨论】:

  • 你没有展示你的实际测试,但你想让我们弄清楚它们有什么问题?
  • 由于字符限制,我不知道它是否允许我这样做。也更新了代码。
  • 你的测试实际上并没有测试任何东西。最有可能的是,每次测试后屏幕都会“清空”。添加断言(假);在您的其他一项测试中,看看会发生什么
  • 作为初学者,我正在尝试了解工厂注释的工作原理。而且我不希望代码很复杂。如果我添加dependOnMethod,我会得到依赖不存在的方法错误
  • 添加断言如何使代码“复杂”? medium.com/geekculture/…

标签: java testng testng.xml testng-annotation-test


【解决方案1】:

目前您的配置是这样的,有 6 个测试实例,每个包含 5 个方法。所以总共这 30 个方法将被传递给拦截方法。因此,由于您使用 getA 对它们进行分组,因此 5 种方法中只有一种方法(最后一种)最终会在地图中用于实例。一种解决方案是通过保留列表映射来实施@Max 的解决方案。

另一种解决方案,假设您使用的是 Java 8+,您可以通过使用排序而不是创建地图来简化拦截方法。

Comparator<IMethodInstance> customCompare = 
   Comparator.comparing(inst -> ((MainImpClass) inst.getInstance()).getA())
             .thenComparing(inst -> inst.getMethod().getPriority());
    
// Now sort the list
list.sort(customCompare);
return list;

有时,这可能会显示一些编译错误,在这种情况下您可以使用:

Comparator<Object> customCompare = 
   Comparator.comparing(inst -> ((MainImpClass) ((IMethodInstance) inst).getInstance()).getA())
             .thenComparing(inst -> ((IMethodInstance) inst).getMethod().getPriority());

注意:最好为工厂和拦截器使用单独的类,因为它们都在做不同的事情。使用entrySet() 迭代地图并使用entry.getValue(),而不是使用keySet() 迭代并通过map.get(key) 访问值。 (Refer)

【讨论】:

  • 你能解释一下methods.sort(customCompare);是什么意思吗?方法是库的一部分吗? P.S:我是编程新手。
  • @Gautham。好点子。我已经更新了我的答案,在刷新页面之后,我看到你提出了类似的想法。 (我没有尝试重复您的答案)。
  • @SurendraAnand 它是作为第一个参数传递的 IMethodInstances 列表。在您的代码中,它是 list
  • 感谢 Max & Gautham 的帮助。您有什么推荐给初学者学习的参考资料吗?
  • @SurendraAnand 官方文档是了解testng的最佳场所
【解决方案2】:

当您尝试将具有相同键的多个值放入映射时,您的 intercept 方法会起作用,因此由于键重复而仅保存最后一个值。

所以你会看到每个班级的最后一个测试..

问题就在这里:

orders.put(Integer.valueOf(testData.getA()), instance);

这里的解决方案可能是

Map<Integer, List<IMethodInstance>> orders

在循环中追加列表。

最后遍历键集并从所有值中创建一个列表。


使用IMethodInterceptor实现排序

要更改测试的顺序,您必须应用一些排序逻辑。

在您的代码中,没有应用排序。您创建了一个新列表,但顺序没有更改。

我将添加一个示例,如何使用自定义比较器按MainImpClass getA() 方法结果应用排序。我会像你现在一样在MainFactoryClass 中添加实现,但通常我会将工厂和侦听器拆分为单独的类。

public class MainFactoryClass implements IMethodInterceptor {

    @Factory
    public Object[] mainFactory() {

        Object[] data = new Object[6];
        data[0] = new MainImpClass(9);
        data[1] = new MainImpClass(10);
        data[2] = new MainImpClass(11);
        data[3] = new MainImpClass(12);
        data[4] = new MainImpClass(13);
        data[5] = new MainImpClass(14);
        return data;
    }

    @Override
    List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
        // applying sorting is essential to change the tests order
        methods.sort(new MainImpClassComparator());
        return methods;
    }

    // internal class added, assumed it should compare only methods from MainImpClass
    // here compareTo delegated to getA() results
    class MainImpClassComparator implements Comparator<IMethodInstance> {

        @Override
        int compare(IMethodInstance o1, IMethodInstance o2) {
            return ((MainImpClass)o1.getInstance()).getA().compareTo(((MainImpClass)o2.getInstance()).getA());
        }
    }


【讨论】:

  • 谢谢,伙计。让我试试看。
猜你喜欢
  • 1970-01-01
  • 2018-11-11
  • 1970-01-01
  • 2021-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-30
  • 2019-10-20
相关资源
最近更新 更多