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

​数据驱动
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 datasourcem_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);@Overridepublic 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);// 你可以在这里根据参数值设置测试类的状态或字段}@Testpublic void testMethod() {// 在这里执行你的测试逻辑}
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/805890.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3实践之全局请求URL配置和请求参数说明

Vue3实践之全局请求URL配置和请求参数说明 全局请求URL配置 1、首先需要导入router和axios import router from "/router";2、创建app&#xff0c;将router挂载到app上 const app createApp(App) app.use(router).use(elementIcons).mount(#app)3、设置全局请求…

安装苹果ipa的方法

1、如何生成udid udid获取工具 https://www.betaqr.com/tools 提示下载后 2、爱思助手安装苹果app mac下载爱思助手&#xff0c;数据线连接手机&#xff0c;把ipa包拖到爱思助手app应用选项里 3、新手机调试需要先选中设备&#xff0c;再注册

VMwear桥接网络正确配置+静态IP设置

1.桥接网络配置 很多时候在VMware安装完虚拟机之后&#xff0c;会发现配置的桥接网络没有起作用&#xff0c;如果是Linux下输入ifconfig发现只有ipv6的地址而没有ipv4&#xff0c;说明没有桥接没有启用成功&#xff0c;需要按照以下方式来设置 在VMware的左上角打开编辑&#…

Redis(持久化 -- RDB AOF)

持久化 通常我们认为持久化为: 重启进程/重启主机之后, 数据仍然存在不丢失 把数据存储在硬盘上 – 持久 把数据存储在内存中 – 不持久 Redis 持久化 redis 是一个内存数据库, 也就是说本身是不持久的(但是快[效率高]), 于是 Redis 提供了持久化机制 — RDB 和 AOF 二者都是对…

H.265网页无插件播放EasyPlayer.js流媒体播放器常见问题及解答

EasyPlayer属于一款高效、精炼、稳定且免费的流媒体播放器&#xff0c;可支持多种流媒体协议播放&#xff0c;无须安装任何插件&#xff0c;起播快、延迟低、兼容性强&#xff0c;使用非常便捷。 今天我们来汇总下用户常见的几个问题及解答。 1、EasyPlayer.js播放多路H.265视…

Android 输入法框架

输入法属于输入系统的一部分&#xff0c;区别于输入系统只能向系统产生时间&#xff0c;输入法能向系统输入具体的内容&#xff0c;下面来认识输入法的大体框架&#xff0c;以下内容参考清华大学出版社出版的《Android图形显示系统》。 输入法框架包含3个组件&#xff0c;各组件…

python画图Matplotlib和Seaborn

python画图Matplotlib和Season 一、Matplotlib1、介绍2、安装3、内容二、Seaborn1、介绍2、安装3、内容一、Matplotlib Matplotlib官网 1、介绍 Matplotlib 是一个 Python 的绘图库,用于创建高质量的二维图表和一些基本的三维图表。它广泛应用于科学计算、数据分析、工程学和…

基于springboot+vue实现的的成人教育教务系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;spring…

uview2 表单Form校验validate不生效处理方法

先贴官网实例&#xff1a; <template><view class""><u-form :model"form" ref"uForm"><u-form-item label"姓名" prop"name"><u-input v-model"form.name" /></u-form-item&g…

AI时代,搜索引擎的巨头地位恐怕不保了

兄弟们&#xff0c;你们使用搜索网站的频率有降低吗&#xff1f; ChatGPT 已经流行了一年多了&#xff0c;这期间数个大模型都发展了起来。 搜索引擎本质上也属于问答系统&#xff0c;所以&#xff0c;在大模型成熟之后&#xff0c;我使用搜索的频率越来越低了。 主要是因为…

python实现pdf的页面替换

利用第三方库PyPDF2&#xff0c;下面例子中进行的是将 origin.pdf 的第17页替换为 s17.pdf 的第1页&#xff1a; import PyPDF2def replace_pages(original_pdf_path, replacement_pages):with open(original_pdf_path, rb) as original_file:original_pdf PyPDF2.PdfReader(…

水牛社:互联网赚钱秘籍,免费项目,你真敢要吗?

免费是最贵的。真正理解并使用这句话的只有少数人&#xff0c;今天在网上分享一下免费项目背后的逻辑&#xff0c;抛开现象&#xff0c; 本质是最重要的。 我从事互联网工作15年。不管是过去还是现在&#xff0c;总有人喜欢问有没有免费项目&#xff1f; 其实我平时懒得回答…

java基础语法(13)

1. final关键字 final概述 学习了继承后&#xff0c;我们知道&#xff0c;子类可以在父类的基础上改写父类内容&#xff0c;比如&#xff0c;方法重写。那么我们能不能随意的继承API中提供的类&#xff0c;改写其内容呢&#xff1f;显然这是不合适的。为了避免这种随意改写的情…

pkg打包nodejs程序用动态require路由出现问题

动态路由问题 pkg打包的时候会自动生成一个虚拟路径/snapshot/…会导致你的路径出现一些问题 而项目中依据route文件夹下的文件动态use相应的router&#xff0c;这就需要动态require&#xff0c;但是这个require的路径会被虚拟路径代替导致取不到&#xff0c;所以可以使用写死…

理解vue2中的watch监听

vue实例组件初始化过程中&#xff0c;在执行initState(vm)方法初始化状态时&#xff0c;判断options.watch有值时会进行initWatch(vm, options.watch)处理&#xff0c;然后对watch对象中的每个watch属性执行createWatcher方法 function initState(vm) {// 传入的watchif (opti…

华为OD机试 - 最多颜色的车辆(Java JS Python C C++)

须知 哈喽,本题库完全免费,收费是为了防止被爬,大家订阅专栏后可以私信联系退款。感谢支持 文章目录 须知题目描述输入描述输出描述解析代码题目描述 在一个狭小的路口,每秒只能通过一辆车,假设车辆的颜色只有 3 种,找出 N 秒内经过的最多颜色的车辆数量。 三种颜色编…

线程与Task的区别 async和await关键字

任务Task和线程Thread的区别&#xff1a; 1、任务是架构在线程之上的&#xff0c;也就是说任务最终还是要抛给线程去执行。 2、任务跟线程不是一对一的关系&#xff0c;比如开10个任务并不是说会开10个线程&#xff0c;这一点任务有点类似线程池&#xff0c;但是任务相比线程池…

C++初阶---vector(STL)

1、vector的介绍和使用 1.1、vector的介绍 1. vector是表示可变大小数组的序列容器。 2. 就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素 进行访问&#xff0c;和数组一样高效。但是又不像数组&#xff0c;它的大小是…

为什么你选择成为一名程序员?

成为一名程序员&#xff0c;是基于多种因素的考量。 首先&#xff0c;对技术和创新的热爱是关键因素之一。编程是一种创造的过程&#xff0c;能够将抽象的想法转化为实际的应用程序和系统&#xff0c;这种创造的满足感令人着迷。 其次&#xff0c;编程领域的广阔发展前景也是…

MATLAB 普通场景的道路点云分割 (方法一)(56)

MATLAB 普通场景的道路点云分割(方法一) (56) 一、分割原理二、算法实现1.代码一、分割原理 基于这样一个认识:大部分情况下,点云都是分块去处理的,在某块点云场景中,点云区域不大,地面基本是水平分布的,不会有较大的坡度,因此将其认为是一个法向与Z轴大致平行的平…