java - Selenium - TestNG - 如何根据并行使用 Maven 命令行传递的参数跳过/禁用某些测试

标签 java selenium maven testng listener

我们有一个跨国网站。并非所有功能在任何地方都可用,即。在所有国家(语言)。我在 Java 堆栈 - TestNG - TestNG 监听器 - Selenium WebDriver(页面对象模型) - Maven 上构建了数百个测试。所有测试均使用 Maven 和命令行从 Jenkins 运行。使用命令行我传递所有必要的参数,即。测试组、baseURL、语言等

一些测试是并行运行的,一些测试是单线程的。由于这个原因,我将 testng.xml 设置如下:

<suite name="Tests">
    <listeners>
        <listener class-name="listeners.TestListener"/>
        <listener class-name="listeners.TestSuiteListener"/>
        <listener class-name="listeners.SkipInCountryMethodInterceptorListener"/>
    </listeners>
    <test name="Parallel tests" parallel="methods" thread-count="8">
        <groups>
            <run>
                <include name="Parallel" />
                <exclude name="SingleThread" />
            </run>
        </groups>
        <packages>
            <package name="tests" />
        </packages>
    </test>
    <test name="Single thread tests" parallel="false">
        <groups>
            <run>
                <include name="SingleThread" />
                <exclude name="Parallel" />
            </run>
        </groups>
        <packages>
            <package name="tests" />
        </packages>
    </test>
</suite>

所有测试都使用整理好的测试注释中的组。

@Test(testName = "testName", priority = Priority.MEDIUM, groups = {TestGroup.SMOKE, TestGroup.SINGLETHREAD})
public void testName () {

}

我正在读取@BeforeSuite中的命令行参数,并将其放入ITestContext的属性中

@BeforeSuite()
@Parameters({ "lang" })
public void beforeSuite(final ITestContext testContext, @Optional("en") String lang) {
...
        testContext.setAttribute("Language", lang);
...
}

我尝试了很多方法如何根据这个参数lang(国家/地区)过滤测试,例如@BeforeMethod(onlyForGroups = {TestGroup.SKIP_IN_EN})SkipException 或使用 IAnnotationTransformersetEnable(false)。我不知道如何将参数传递给变压器并将其用于条件。没有 ITestContext 并且看起来 transformer@BeforeSuite 之前调用,所以在我能够读取命令行属性之前。

对我来说部分有用的是IMethodInterceptor。我创建了一个新的测试组 SkipIn[Language],例如 SkipInHUSkipInEN,...怎么说,应该跳过此测试方法

public class SkipInCountryMethodInterceptorListener implements IMethodInterceptor {

    @Override
    public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
        List<IMethodInstance> result = new ArrayList<IMethodInstance>();
        for (IMethodInstance method : methods) {
            Test testMethod = method.getMethod().getConstructorOrMethod().getMethod().getAnnotation(Test.class);
            Set<String> groups = new HashSet<String>();
            for (String group : testMethod.groups()) {
                groups.add(group);
            }

            String language = "en";

            Set<String> attrs = context.getAttributeNames();
            if (attrs.contains("Language")) {
                try {
                    language = context.getAttribute("Language").toString();
                } catch (Exception ignored) {}
            }

            if (groups.contains(TestGroup.SKIP_IN_EN) && language.equals("en")) {
                Log.info("TestMethod skipped.");
            } else {
                result.add(method);
            }

        }

        return result;
    } 

但是这个解决方案在并行运行测试时存在问题。我不知道为什么,也许是不同的线程,但 @BeforeSuite 无法将属性放入 ITestContext 中。在IMethodInterceptor中,ITestContext的每次属性都是空的(属性Language为null,不存在),并且只有@BeforeClass工作良好(读取maven参数) ,但这是在调用了 IMethodInterceptor 之后。

过滤国家/地区测试的最佳想法是什么?

我可以说,90% 的测试是全局性的,因此从我的角度来看,为每个国家/地区设立一个测试组并通过我想要运行的一组测试并不是一个好方法。因为在一项测试中,我可能还需要有 10 个不同的组,并且对于每个新的国家/地区,我都应该为每个测试添加新的测试组。

感谢您的帮助或想法。

最佳答案

您可以使用IAnnotationTransformer。例如,这是我的测试类:

public class TestSkip {

    @Test(testName = "ruTest", groups = {"RU_TESTS"})
    public void ruTest(){
        System.out.println("Running RU test");
        Assert.assertTrue(true);
    }

    @Test(testName = "enTest", groups = {"EN_TESTS"})
    public void enTest(){
        System.out.printf("Running EN test");
        Assert.assertTrue(true);
    }

}

这是我的testng.xml

<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="Suite1" verbose="1" >
    <listeners>
        <listener class-name="click.webelement.testng.TestSkipTransformer"/>
    </listeners>
    <test name="SO-answer">
        <packages>
            <package name="click.webelement.testng" />
        </packages>
    </test>
</suite>

这是我的注释转换器实现:

public class TestSkipTransformer implements IAnnotationTransformer {

    @Override
    public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
        String language = System.getProperty("lang", "EN");
        if ("EN".equals(language)
                && !Arrays.asList(annotation.getGroups()).contains("EN_TESTS")) {
            annotation.setEnabled(false);
        }
        if ("RU".equals(language)
                && !Arrays.asList(annotation.getGroups()).contains("RU_TESTS")) {
            annotation.setEnabled(false);
        }
    }
}

这是我设置参数的万无一失的设置(不处理命令行参数)

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0-M4</version>
    <configuration>
        <suiteXmlFiles>
            <suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
        </suiteXmlFiles>
            <systemPropertyVariables>
                <lang>RU</lang>
            </systemPropertyVariables>
    </configuration>
</plugin>

关于java - Selenium - TestNG - 如何根据并行使用 Maven 命令行传递的参数跳过/禁用某些测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61912489/

相关文章:

java - 数据库到GlazedList/Jtable,然后通过GlazedList/JTable编辑数据库

使用 Selenium 的 C# 代码覆盖率

java - 部署 jar 文件时出现问题 : Error dependencies

maven - 如何将 WSDL、XSD(以及可能的其他文件)添加到 WAR

java - Maven 缺少 Artifact org.geotools :gt-shapefile:jar:11-SNAPSHOT

java - 为什么 s 是 :mvcUrl function returning different results on different views?

java - 如何使用 JUNG 在给定坐标中绘制节点

java - 为 Hazelcast 配置 Java 客户端

javascript - 将 Javascript 注入(inject) selenium Python -> Converted_args}) ['value' ]

testing - selenium webdriver中frame没有id时如何识别并切换到frame