使用提供程序时覆盖 TestNG 测试名称并省略参数 [英] Override TestNG Test name when using a provider and omit parameters

查看:31
本文介绍了使用提供程序时覆盖 TestNG 测试名称并省略参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

具有以下示例代码......在运行测试(和报告)时,我希望将测试名称设置为提供者提供的描述字段(实际上它是任何字符串).

...但是,即使从 ITest 扩展,似乎所有提供程序参数都附加到 TestName,我想要的只是描述.

所以实际的测试名称应该是 "TestName1" 而不是 "TestName2[1](TestName2, 2, 2, 4)" .. 这是 XML 报告中显示的内容,以及 test.aftertest 名称.

import org.testng.Assert;导入 org.testng.ITest;导入 org.testng.annotations.BeforeMethod;导入 org.testng.annotations.DataProvider;导入 org.testng.annotations.Test;导入 java.lang.reflect.Method;公共类 TestNgProviderExample 实现 ITest{@Test(dataProvider = "summationProvider")public void testProvider(String description, int number1, int number2, int sum) {Assert.assertEquals(sum, number1 + number2);}@DataProvider(name = "summationProvider")公共对象[][] summationData() {Object[][] testData = {{"TestName1",1,2,3},{"TestName2",2,2,4}};返回测试数据;}私人字符串报告测试名称 = "";@BeforeMethod(alwaysRun = true)public void testData(Method method, Object[] testData) {reportTestName = testData[0].toString();}@覆盖公共字符串 getTestName() {返回报告的测试名称;}}

解决方案

只需运行一个@Test-注解不带参数的方法即可解决.
我的解决方案没有使用参数,而是使用类字段和构造函数 @Factory 方法.

public class TestClass 实现 ITest {受保护的字符串描述;受保护的 int firstNumber;受保护的 int secondNumber;受保护的整数总和;@测试公共无效测试提供者(){/*** 减号或加号在这里使它失败或通过.*/assertEquals(this.sum, this.firstNumber - this.secondNumber);}@Factory(dataProvider = "summationProvider")公共测试类(字符串描述,int firstNumber, int secondNumber, int sum) {this.description = 描述;this.firstNumber = firstNumber;this.secondNumber = secondNumber;this.sum = 总和;}@DataProvider(name = "summationProvider")公共静态对象[][] summationData() {Object[][] testData = {{"TestName1", 1, 2, 3}, {"TestName2", 2, 2, 4}};返回测试数据;}@覆盖公共字符串 getTestName() {返回 this.description;}}

从我的 IntelliJ Idea 输出格式:

当然,可以让 @Factory 实例化另一个类,而不是同一个 TestClass.

如果您有 40 个独立的参数变量并希望保持简短...添加一个类作为这些参数的持有者,例如参数化输入.它至少可以隐藏所有这些实例变量.您也可以将 description 放在第二个类中(在这种情况下,建议使用 ThreadLocal 使用).
第二个类将随着参数增长,但由于它是一个普通的旧 Java 对象,它不应该在测试中破坏任何东西.如果您不想设置所有这些变量,另一个想法是在测试中延迟访问参数.按照专家 (

Have the following Sample code ... when running tests (and in reports), I would like the Test Names to be set to the description field provided by the provider (really it's any String).

... however, even when extending from ITest, it seems like all the provider parameters get appended to the TestName, what I want is the description only.

So actual test name should be "TestName1" instead of "TestName2[1](TestName2, 2, 2, 4)" .. which is what is showing up in XML reports, and test.aftertest name.

import org.testng.Assert;
import org.testng.ITest;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.lang.reflect.Method;

public class TestNgProviderExample implements ITest{

    @Test(dataProvider = "summationProvider")
    public void testProvider(String description, int number1, int number2, int sum) {
        Assert.assertEquals(sum, number1 + number2);
    }

    @DataProvider(name = "summationProvider")
    public Object[][] summationData() {
        Object[][] testData = {{"TestName1",1,2,3},{"TestName2",2,2,4}};
        return testData;
    }

    private String reportedTestName = "";

    @BeforeMethod(alwaysRun = true)
    public void testData(Method method, Object[] testData) {
        reportedTestName = testData[0].toString();
    }

    @Override
    public String getTestName() {
        return reportedTestName;
    }
}

解决方案

Simply running a @Test-annotated method without parameters can solve it.
Instead of parameters my solution uses class fields and a constructor @Factory method.

public class TestClass implements ITest {

    protected String description;
    protected int firstNumber;
    protected int secondNumber;
    protected int sum;

    @Test
    public void testProvider() {
        /**
         * Minus or plus here to make it fail or pass.
         */
        assertEquals(this.sum, this.firstNumber - this.secondNumber);
    }

    @Factory(dataProvider = "summationProvider")
    public TestClass(String description,
                     int firstNumber, int secondNumber, int sum) {
        this.description = description;
        this.firstNumber = firstNumber;
        this.secondNumber = secondNumber;
        this.sum = sum;
    }

    @DataProvider(name = "summationProvider")
    public static Object[][] summationData() {
        Object[][] testData = {{"TestName1", 1, 2, 3}, {"TestName2", 2, 2, 4}};
        return testData;
    }

    @Override
    public String getTestName() {
        return this.description;
    }
}

Output with formatting from my IntelliJ Idea:

Of course, it is possible to make the @Factory instantiate another class, not the same TestClass.

And if you have 40 separate variables from parameters and want to keep it short... Add a class that would be a holder for those parameters, e.g. ParametrizedInput. It would at least make it possible to hide all those instance variables. You can place description in the second class as well (in that case ThreadLocal<ParametrizedInput> usage would be advised).
The second class will grow with parameters, but since it is a plain old Java object, it shouldn't break anything in test. If you don't want to set all those variables, another idea would be to access parameters lazily in tests. Following expert's (Krishnan Mahadevan) advice I figured out that the name with a method can be set with a @BeforeMethod- and @AfterMethod-annotated methods.

public class TestClass implements ITest {

    protected static ThreadLocal<String> description
            = new ThreadLocal<>();
    protected ParametrizedInput input;

    @BeforeMethod
    public void setUp(Method method) {
        this.description.set(this.description.get() + " " + method.getName());
    }

    @AfterMethod
    public void tearDown(Method method) {
        this.description.set(this.description.get().substring(0,
                this.description.get().length() - method.getName().length()));
    }

    @Test
    public void testProvider() {
        assertEquals(this.input.getSum(),
                this.input.getFirstNumber() / this.input.getSecondNumber());
    }

    @Test
    public void anotherTestProvider() {
        assertEquals(this.input.getSum(),
                this.input.getFirstNumber() - this.input.getSecondNumber());
    }
    @Factory(dataProvider = "summationProvider")
    public TestClass(String descriptionString, ParametrizedInput input) {
        this.description.set(descriptionString);
        this.input = input;
    }

    @DataProvider(name = "summationProvider")
    public static Object[][] summationData() {
        Object[][] testData = {{"TestName1", new ParametrizedInput(1, 2, 3)},
                {"TestName2", new ParametrizedInput(2, 2, 4)}};
        return testData;
    }

    @Override
    public String getTestName() {
        return this.description.get();
    }
}

Parameter Holder class:

public class ParametrizedInput {

    private int firstNumber;
    private int secondNumber;
    private int sum;

    public ParametrizedInput(int firstNumber,
                             int secondNumber, int sum) {
        this.firstNumber = firstNumber;
        this.secondNumber = secondNumber;
        this.sum = sum;
    }

    public int getFirstNumber() {
        return firstNumber;
    }

    public int getSecondNumber() {
        return secondNumber;
    }

    public int getSum() {
        return sum;
    }
}

Result:

这篇关于使用提供程序时覆盖 TestNG 测试名称并省略参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆