Testng测试框架(4)-数据驱动@Parameters

本文详细介绍了如何在TestNG中使用@Parameters注解传递参数,包括testng.xml文件、Java系统属性和数据提供者,以及如何控制线程池和利用系统属性进行参数传递。
摘要由CSDN通过智能技术生成

​数据驱动
Testng使用 @Parameters注释传递任意参数给测试用例

There are three ways to set these parameters 有三种方法设置参数:
1、testng.xml文件
2、Programmatically
3、Java system properties

testng.xml文件中的参数

@Parameters({ "first-name" })
@Test
public void testSingleString(String firstName) {
  System.out.println("Invoked testString " + firstName);
  assert "Cedric".equals(firstName);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Suite1">
    <parameter name="first-name"  value="Cedric"/>
    <test name="Test1">
        <classes>
            <class name="TestNGSimpleTest"/>
        </classes>
    </test>
</suite>

同样的方法也可以用于 @Before/@After and @Factory 注释

@Parameters({ "datasource", "jdbc-driver" })
@BeforeMethod
public void beforeTest(String ds, String driver) {
  m_dataSource =  buildDataSource();    // look up the value of datasource
  m_jdbcDriver = driver;
}

This time, the two Java parameter ds and driver will receive the value given to the properties datasource and jdbc-driver respectively.

参数可以使用 org.testng.annotations.Optional 注释定义为可选参数。

@Parameters("db")
@Test
public void testNonExistentParameter(@Optional("mysql") String db) {
    //more code
}

If no parameter named “db” is found in your testng.xml file, your test method will receive the default value specified inside the @Optional annotation: “mysql”.

@Parameters 注解可以放置在以下位置:

在任何已经带有 @Test、@Before/@After 或 @Factory 注解的方法上。

在您的测试类中的最多一个构造器上。在这种情况下,每当 TestNG 需要实例化您的测试类时,它都会使用 testng.xml 中指定的值初始化参数,然后调用这个特定的构造器。此功能可用于将类中的字段初始化为值,然后这些值将被您的测试方法使用。

Important:
The XML parameters are mapped to the Java parameters in the same order as they are found in the annotation, and TestNG will issue an error if the numbers don’t match.

Parameters are scoped. In testng.xml, you can declare them either under:

tag or

tag or

tag or

tag.

The order of precedence (lowest to highest) in terms of resolving values for parameters with same names is

<suite> --> <test> --> <class> --> <methods>

DataProvider

如果您需要传递复杂的参数,或者需要从 Java 创建的参数(如复杂对象、从属性文件或数据库中读取的对象等),那么在 testng.xml 中指定参数可能不足够。在这种情况下,您可以使用数据提供者(Data Provider)来提供您需要的测试值。数据提供者是一个返回对象数组的方法,位于您的类上。这个方法用 @DataProvider 注解标记。

使用数据提供者,您可以创建复杂的测试场景,其中参数可以根据运行时条件或程序逻辑动态生成。这增加了测试的灵活性和可维护性,特别是当您处理复杂的数据集或需要从外部源(如数据库或文件)加载测试数据时。

当 TestNG 运行测试时,它会查找并使用带有 @DataProvider 注解的方法,以获取需要传递给测试方法的参数。这使得测试更加灵活,因为您可以在测试运行时根据需要动态生成参数。这有助于确保测试覆盖更多的场景和边缘情况,从而提高代码的质量和可靠性。

TestNG 文档

//This method will provide data to any test method that declares that its Data Provider
//is named "test1"
@DataProvider(name = "test1")
public Object[][] createData1() {
 return new Object[][] {
   { "Cedric", 36 },
   { "Anne", 37},
 };
}
//This test method declares that its data should be supplied by the Data Provider
//named "test1"
@Test(dataProvider = "test1")
public void verifyData1(String n1, Integer n2) {
 System.out.println(n1 + " " + n2);
}

. @Test方法使用dataProvider属性来指定它的数据提供者,提供name参数来查找同一个类中使用@DataProvider(name=“…​”) 注释的方法。data prov,则需要ider默认在当前测试类或者它的测试基类红查找,如果你想把data provider存在不同的类中,则需要在dataProviderClass属性中指定类名。

public class StaticProvider {
  @DataProvider(name = "create")
  public static Object[][] createData() {
    return new Object[][] {
      new Object[] { 42 }
    };
  }
}
public class MyTest {
  @Test(dataProvider = "create", dataProviderClass = StaticProvider.class)
  public void test(Integer n) {
    // ...
  }
}

重试data providers

import org.testng.IDataProviderMethod;
import org.testng.IRetryDataProvider;
import java.util.concurrent.atomic.AtomicInteger;
public class RetryDataProvider implements IRetryDataProvider {

    private final AtomicInteger counter = new AtomicInteger(1);

    @Override
    public boolean retry(IDataProviderMethod dataProvider) {
        boolean status = counter.getAndIncrement() <= 2;
        String clazz = dataProvider.getMethod().getDeclaringClass().getName();
        String dataProviderMethodName = dataProvider.getMethod().getName();
        String methodName = clazz + "." + dataProviderMethodName + "()";
        System.err.println("Retry the data provider method " + methodName + " ? " + status);
        return status;
    }
}

这个RetryDataProvider类实现了IRetryDataProvider接口,其中只有一个方法retry。这个方法接收一个IDataProviderMethod参数,判断是否需要重试该数据提供者方法。
首先,使用counter.getAndIncrement()获取并增加当前的重试计数,判断是否小于等于2。
然后,通过dataProvider.getMethod()获取当前数据提供者方法的信息,包括类名和方法名。
接着,将类名、方法名拼接成完整的方法字符串methodName。
最后,打印输出重试信息,并返回是否需要重试的布尔值。
总结:该函数用于判断是否需要重试某个数据提供者方法,基于一个重试计数器的值。

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class RetriableDataProviderSample {

    private boolean throwException = true;

    @Test(dataProvider = "test-data")
    public void sampleTestMethod(int input) {
        System.err.println("Input value = " + input);
    }

    @DataProvider(retryUsing = RetryDataProvider.class, name = "test-data")
    public Object[][] testDataSupplier() {
        if (throwException) {
            throwException = false;
            System.err.println("Simulating a problem when invoking the data provider");
            throw new IllegalStateException("Simulating a failure in data provider");
        }
        return new Object[][]{
                {1}, {2}
        };
    }
}

该Java类是一个测试类,使用了TestNG框架。类中包含一个测试方法sampleTestMethod和一个数据提供者方法testDataSupplier。
sampleTestMethod方法接收一个整数参数input,并打印出输入值。
testDataSupplier方法通过@DataProvider注解标记为数据提供者,提供给sampleTestMethod使用。该方法使用retryUsing属性指定了RetryDataProvider类作为重试机制。数据提供者方法返回一个二维Object数组,其中每个一维数组代表一个测试用例的数据。在该例子中,数据提供者方法返回了两个测试用例的数据:{1}和{2}。
@Test注解标记了sampleTestMethod为测试方法,并指定了数据提供者为test-data。
值得注意的是,在testDataSupplier方法中,通过判断throwException变量的值来模拟数据提供者发生异常的情况。如果throwException为true,则将它设置为false,打印一条错误信息,并抛出一个IllegalStateException异常。这样,在测试执行时,第一次调用数据提供者会抛出异常,而由于配置了重试机制,会再次调用数据提供者,从而提供正确的测试数据进行测试。

控制线程池的使用

在 TestNG 中,控制线程池的使用可以帮助你管理测试的执行,特别是在进行并行测试时。TestNG 允许你配置线程池的大小,以便同时运行多个测试方法或测试类。这可以提高测试的执行速度,但也可能导致资源竞争或测试之间的干扰,因此合理地控制线程池的使用至关重要。

要控制 TestNG 的线程池使用,你可以使用 testng.xml 配置文件中的 或 标签的 thread-count 属性。这个属性指定了用于执行测试的线程数。例如:

<suite name="MyTestSuite" thread-count="5">  
    <test name="MyTest">  
        <classes>  
            <class name="com.example.MyTestClass"/>  
        </classes>  
    </test>  
</suite>

在这个例子中,thread-count 被设置为 5,意味着 TestNG 将使用一个包含 5 个线程的线程池来执行 MyTestSuite 中的测试。

请注意以下几点:

线程安全性:当使用多线程执行测试时,你需要确保你的测试代码是线程安全的。这包括避免共享可变状态,除非这种共享是明确且受控的。

资源限制:线程池的大小应该根据你的系统资源(如 CPU 核心数、内存大小)和测试需求来设置。过多的线程可能导致系统资源耗尽,反而降低测试执行效率。

测试依赖:如果你的测试之间有依赖关系(例如,一个测试需要在另一个测试之后运行),那么多线程执行可能会导致问题。在这种情况下,你可能需要仔细设计你的测试,或者使用其他机制(如依赖注入或测试顺序控制)来管理依赖。

并行级别:TestNG 提供了不同的并行级别,如方法级并行(每个方法一个线程)、类级并行(每个类一个线程)等。你可以通过配置 parallel 属性来指定所需的并行级别。

动态分配:虽然你可以指定线程池的大小,但 TestNG 实际上会根据可用的测试方法和配置的并行级别来动态地分配线程。这意味着并不是所有线程都会同时运行;它们会根据需要被创建和销毁。

通过合理地配置线程池和使用 TestNG 的并行测试功能,你可以提高测试的执行效率,同时确保测试的稳定性和可靠性。

Parameters from System Properties

TestNG can be passed parameters on the command line of the Java Virtual Machine using system properties (-D).这种方法传递的参数不需要事先在testng.xml文件中定义,也可以覆盖testng.xml预先定义的参数值。

java -Dfirst-name=Cedrick -Dlast-name="von Braun" org.testng.TestNG testng.xml

The Java system property variable is a string with no spaces that represents the name of the property. The value variable is a string that represents the value of the property. If the value is a string with spaces, then enclose it in quotation marks.

在TestNG 6.x版本,在testng.xml中定义的参数不会被系统属性fugitive。

在 TestNG 中,你可以从系统属性(System Properties)中获取参数,并在测试中使用这些参数。系统属性通常是在 JVM 启动时设置的,并且可以通过 System.getProperty() 方法在 Java 代码中进行访问。TestNG 提供了一种机制,允许你将系统属性的值作为参数传递给测试方法。

要从系统属性中获取参数,你需要在 testng.xml 配置文件中使用 <parameter> 标签,并指定一个名字。然后,在测试方法中使用 @Parameters 注解来声明这个参数。TestNG 会自动查找具有相同名字的系统属性,并将其值传递给测试方法。

下面是一个简单的示例,展示了如何从系统属性中获取参数:

  1. testng.xml 配置:
<suite name="MySuite">
    <test name="MyTest">
        <parameter name="myParam" value="${systemProperty}" />
        <classes>
            <class name="com.example.MyTestClass" />
        </classes>
    </test>
</suite>

在这个例子中,我们定义了一个名为 myParam 的参数,并将其值设置为 ${systemProperty}。这意味着 TestNG 会查找名为 systemProperty 的系统属性,并将其值赋给 myParam

  1. 设置系统属性:

在运行测试之前,你需要设置相应的系统属性。这可以通过在 JVM 启动时添加 -D 参数来实现。例如,在命令行中运行 TestNG 时,你可以这样做:

java -DsystemProperty=myValue -jar testng.jar testng.xml

在这个例子中,我们设置了名为 systemProperty 的系统属性,其值为 myValue

  1. 测试类中的使用:

在你的测试类中,你可以使用 @Parameters 注解来声明一个方法,该方法将接收在 testng.xml 中定义的参数。然后,你可以在测试方法中使用这些参数。

import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class MyTestClass {

    @Parameters({"myParam"})
    public void setUp(String myParam) {
        // 在这里,myParam 将被赋值为系统属性的值,即 "myValue"
        System.out.println("Parameter value from system property: " + myParam);
        // 你可以在这里根据参数值设置测试类的状态或字段
    }

    @Test
    public void testMethod() {
        // 在这里执行你的测试逻辑
    }
}

在这个例子中,setUp 方法被标记为 @Parameters,并接受一个字符串参数 myParam。当 TestNG 运行测试时,它会查找名为 myParam 的参数(在 testng.xml 中定义),并查找相应的系统属性(在这里是 systemProperty)。然后,它将系统属性的值(即 “myValue”)传递给 setUp 方法。你可以在 setUp 方法中使用这个值来初始化测试类的状态或字段。

  • 27
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值