当前位置: 首页 > 知识库问答 >
问题:

TestNG中测试执行顺序的问题

鲜于允晨
2023-03-14

我有一个包-'脚本'

根据剧本,我有两个类别——甲和乙

在一个类中,我有3个方法(@Test)按顺序编写-

@Test(priority=1)
public void b(){ }

@Test(priority=2)
public void a(){}

@Test(priority=3)
public void d(){}

在B班我有一种方法-

@Test
public void c(){}

TestNG. XML

<classes>
  <class name="scripts.A"/>
  <class name="scripts.B"/>
</classes>

在执行时——作为TestNG套件——右键单击TestNG XML并选择Run as a TestNG Suite

  1. 类B首先执行-这是因为类B中的@Test没有指定优先级,因此成为最高优先级

有没有办法让@Test的优先级只在类中起作用?为什么TestNG比较所有类中所有测试方法的优先级,然后计划执行。此外,由于我在TestNG XML中定义了类的执行顺序,很明显,我希望第二类方法在第一类方法之后执行。在这种情况下,预期的执行顺序应该是——首先是A的方法,然后是B的方法。

怎么逃脱呢?

共有1个答案

暨嘉
2023-03-14

默认情况下,TestNG首先收集所有方法,然后根据它们的优先级对它们进行排序(它不会根据它们之前出现的类对它们进行分类)。话虽如此,下面是您的操作方法。

  1. 首先确保您的@Test方法不使用优先级属性(或者)您在套件xml文件中显式地将保持顺序设置为false
  2. 然后构建一个方法拦截器,它首先根据类在套件xml文件中出现的顺序对方法进行排序,然后使用自定义注释,该注释服务于相同的优先级排序机制。

这应该能满足你的需求。

这是你的A课程的样子:

import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.annotations.Test;

public class TestClassASample {
    @Test
    @PriorityInClass(priority = 1)
    public void a() {
        System.err.println(stringify());
    }

    @Test
    @PriorityInClass(priority = 2)
    public void b() {
        System.err.println(stringify());
    }

    @Test
    @PriorityInClass(priority = 3)
    public void c() {
        System.err.println(stringify());
    }

    private String stringify() {
        ITestResult result = Reporter.getCurrentTestResult();
        return result.getTestClass().getRealClass().getName() + "." + result.getMethod().getMethodName() + "()";
    }
}

这是您的B类的外观:

import org.testng.ITestResult;
import org.testng.Reporter;
import org.testng.annotations.Test;

public class TestClassBSample {
    @Test
    public void c() {
        System.err.println(stringify());
    }

    private String stringify() {
        ITestResult result = Reporter.getCurrentTestResult();
        return result.getTestClass().getRealClass().getName() + "." + result.getMethod().getMethodName() + "()";
    }
}

自定义注释的外观如下:

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.METHOD;

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({METHOD})
public @interface PriorityInClass {
    int priority() default 0;
}

下面是方法拦截器的外观:

import org.testng.IMethodInstance;
import org.testng.IMethodInterceptor;
import org.testng.ITestContext;
import org.testng.xml.XmlClass;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class MethodOrderer implements IMethodInterceptor {
    @Override
    public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
        Map<Class, List<IMethodInstance>> mapping = new LinkedHashMap<>();
        List<XmlClass> xmlClasses = context.getCurrentXmlTest().getXmlClasses();
        for (XmlClass xmlClass : xmlClasses) {
            Class<?> clazz = xmlClass.getSupportClass();
            mapping.put(clazz, new ArrayList<>());
            for (IMethodInstance method : methods) {
                Class<?> methodClass = method.getMethod().getTestClass().getRealClass();
                if (mapping.containsKey(methodClass)) {
                    List<IMethodInstance> methodInstances = mapping.get(methodClass);
                    if (!methodInstances.contains(method)) {
                        methodInstances.add(method);
                    }
                }
            }
        }
        List<IMethodInstance> returnValue = new ArrayList<>(methods.size());
        Sorter sorter = new Sorter();
        for (Map.Entry<Class, List<IMethodInstance>> each : mapping.entrySet()) {
            List<IMethodInstance> methodInstances = each.getValue();
            Collections.sort(methodInstances, sorter);
            returnValue.addAll(methodInstances);
        }
        return returnValue;
    }

    public static class Sorter implements Comparator<IMethodInstance> {

        @Override
        public int compare(IMethodInstance o1, IMethodInstance o2) {
            PriorityInClass o1Priority = getPriority(o1);
            PriorityInClass o2Priority = getPriority(o2);
            int priorityO1 = (o1Priority == null ? getPriorityViaTestAnnotation(o1) : o1Priority.priority());
            int priorityO2 = (o2Priority == null ? getPriorityViaTestAnnotation(o1) : o2Priority.priority());
            return (priorityO1 < priorityO2) ? -1 : ((priorityO1 == priorityO2) ? 0 : 1);
        }

        private PriorityInClass getPriority(IMethodInstance instance) {
            return instance.getMethod().getConstructorOrMethod().getMethod().getAnnotation(PriorityInClass.class);
        }

        private int getPriorityViaTestAnnotation(IMethodInstance instance) {
            return instance.getMethod().getPriority();
        }
    }
}

下面是套件xml的样子

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="suite">
    <listeners>
        <listener class-name="com.rationaleemotions.stackoverflow.qn46748930.MethodOrderer"/>
    </listeners>
    <test name="random_test"  preserve-order="false">
        <classes>
            <class name="com.rationaleemotions.stackoverflow.qn46748930.TestClassASample"/>
            <class name="com.rationaleemotions.stackoverflow.qn46748930.TestClassBSample"/>
        </classes>
    </test> <!-- random_test -->
</suite> <!-- suite -->

以下是输出:

com.rationaleemotions.stackoverflow.qn46748930.TestClassASample.a()
com.rationaleemotions.stackoverflow.qn46748930.TestClassASample.b()
com.rationaleemotions.stackoverflow.qn46748930.TestClassASample.c()
com.rationaleemotions.stackoverflow.qn46748930.TestClassBSample.c()

===============================================
suite
Total tests run: 4, Failures: 0, Skips: 0
===============================================
 类似资料:
  • 我正在使用@dataprovider TestNG 注释来传递不同的数据集。我的 TestNG 类包含 @BeforeClass、@DataProvider、三种@Test方法(一种使用数据提供程序的测试)和@After类。 数据提供程序包含 3 组数据(用户名和密码) 我只想知道如何按照以下顺序执行测试 --执行@Beforeclass - --转到测试并从数据提供程序打印第二组数据 --执行第

  • 主要内容:1 概述,2 测试执行顺序,3 例子,4 结论1 概述 在本指南中,我们将学习如何按顺序执行测试。默认情况下,JUnit以任何顺序执行测试。 2 测试执行顺序 要更改测试执行顺序,只需使用@FixMethodOrder注释测试类并指定可用的MethodSorters之一: @FixMethodOrder(MethodSorters.JVM):按照JVM返回的顺序保留测试方法。此顺序可能因运行而异。 @FixMethodOrder(Method

  • 下面TestNG执行测试用例会导致失败。错误-org.openqa.selenium.WebDriverExcture:在处理命令时发生了未知的服务器端错误。原始错误:无法将命令代理到远程服务器。原始错误:错误:套接字挂断(警告:服务器没有提供任何堆栈跟踪信息)命令持续时间或超时: 56毫秒

  • 我正在尝试使用testng.xml执行testcases。我已经将所有的测试运行类放在一个测试中。在执行时,我注意到第二类(仪表板类)的@beforeTest方法首先执行。我希望执行所有类的@beforeTest方法,以与testng.xml文件中的类相同的执行顺序执行。请看下面的图片。 对于我在提到的类中使用的所有@beforeTest和@beforeClass我都使用了waysrun=true

  • 问题内容: 我正在使用pytest。我的目录中有两个文件。在其中一个文件中,有一个长时间运行的测试用例,它会生成一些输出。在另一个文件中,有一个测试用例读取该输出。如何确保两个测试用例的正确执行顺序?除了以适当的顺序将测试用例放入同一文件之外,还有其他选择吗? 问题答案: 通常,您可以使用其明确指定的hook来配置pytest基本上任何部分的行为。 对于您的情况,您需要“ pytest_colle

  • TestNG在执行时混合了来自不同类的测试。每节课都有一些测试。而不是像这样执行: > FirstTestClass firstTest 第一次测试第二次测试 第一班第三班 SecondTestClass firstTest 它是这样执行的,混合了来自每个类的测试: FirstTestClass firstTest 这是我的XML: 我所有的测试都设置了优先级参数。但它应该只影响类内的测试,而不是