如果测试方法不存在,则阻止 TestNG 继续套件

Posted

技术标签:

【中文标题】如果测试方法不存在,则阻止 TestNG 继续套件【英文标题】:Prevent TestNG from continuing suite if a test method does not exist 【发布时间】:2021-02-21 12:49:26 【问题描述】:

这会导致大量的调试混乱,我认为必须有一种方法来防止这种情况发生。现在,如果一个测试方法不存在(比如拼写错误),套件将跳过该方法并继续下一个没有问题的方法。这会导致很多问题,很难找到原因。这是一个例子:

    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Sampoe_testSuite" preserve-order="true">
    <listeners>
        <listener class-name="framework.Listener"/>
    </listeners>
    <test name="Sample_TestSuite-Part1" preserve-order="true">
        <classes>
            <class name="tests.FirstTest">
                <methods>
                    <include name="firstMethod"/>
                </methods>
            </class>
            <class name="tests.SecondTest">
                <methods>
                    <include name="secondMethod"/>
                    <include name="thirdMethod"/>
                </methods>
            </class>
            <class name="tests.ThirdTest">
                <methods>
                    <include name="fourthMethod"/>
                </methods>
            </class>
        </classes>
    </test>
</suite>

假设我拼错了 SecondTest 的 secondMethod。它实际上是代码中的 sceondMethod。当我运行这个套件时,不会有错误,但是会发生什么:

Runs FirstTest.firstMethod
Runs SecondTest.thirdMethod
Runs ThirdTest.fourthMethod

请注意,它只是跳过拼写错误的方法并愉快地继续。我希望它使套件失败并说缺少方法。这可能吗?

【问题讨论】:

【参考方案1】:

您必须实现自己的 SuiteListener 类来实现 ISuiteListener。 实现onStart 方法,它将XML 文件中包含的方法与测试目录中存在的方法进行比较。 如果有,使用System.exit(0)停止执行。

import org.testng.*;
import org.testng.annotations.Test;
import org.testng.xml.XmlInclude;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class SuiteListener implements ISuiteListener 

    @Override
    public void onStart(ISuite suite) 
        // getting included method names in XML suite file
        List<String> inclduedMethodsInXmlSuite =
                suite.getXmlSuite().getTests().stream()
                        .flatMap(xmlTest -> xmlTest.getClasses().stream()
                                .flatMap(xmlClass -> xmlClass.getIncludedMethods().stream()
                                        .map(XmlInclude::getName)))
                        .collect(Collectors.toList());

        // getting all test methods
        List<String> testMethods = new ArrayList<>();
        try (Stream<Path> paths = Files.walk(Paths.get("./src/test/java")))  // path to test classes directory
            testMethods = paths
                    .filter(path -> path.getFileName().toString().endsWith(".java")) // filtering only classes, not directories
                    .map(path -> path.getParent().getFileName().toString() + "." + path.getFileName().toString()) // mapping to qualified name, e.g test.TestClass
                    .map(file -> file.substring(0, file.length() - 5)) // removing ".java"
                    .map(clazz -> 
                                try 
                                    return Class.forName(clazz); // casting to Class object
                                 catch (ClassNotFoundException e) 
                                    e.printStackTrace();
                                    return null;
                                
                            
                    )
                    .flatMap(clazz -> Arrays.stream(clazz.getDeclaredMethods()) // getting methods of a test class annotated with @Test
                            .filter(method -> method.isAnnotationPresent(Test.class)))
                    .map(Method::getName) // mapping to method name
                    .collect(Collectors.toList());
         catch (IOException e) 
            e.printStackTrace();
        

        // checking if any of xml suite methods does not exist in test methods
        final List<String> finalTestMethods = testMethods;
        List<String> notSupprtedMethods = inclduedMethodsInXmlSuite.stream()
                .filter(xmlMethod -> !finalTestMethods.contains(xmlMethod))
                .collect(Collectors.toList());

        if (notSupprtedMethods.size() > 0) 
            System.out.println("Unsupported methods in XML Suite file:");
            notSupprtedMethods.forEach(System.out::println);
            System.exit(0);
        

    

    @Override
    public void onFinish(ISuite suite) 

    


【讨论】:

这有几个问题。一、java是一种编译语言,所以执行jar文件的机器上只存在一个jar,所有的.java都编译成.class。因此,在执行测试套件的机器上没有包含任何 .java 的路径。第二,可能有几十个 java 文件,每个文件都有几十个测试方法。这可能会为每次运行增加大量时间。

以上是关于如果测试方法不存在,则阻止 TestNG 继续套件的主要内容,如果未能解决你的问题,请参考以下文章

TestNG 可以运行多个套件吗?

TestNg的基础知识一

TestNg的基础知识一

Maven 故障安全插件不运行 testNG XML 套件

SpringBootTest 和Testng组成测试套件

Eclipse -- Testng 引用不存在的项目 XXX,启动配置