TestNG中DataProvider的用法二:带懒加载的数据驱动

时间:2023-01-31 17:46:49

@DataProvider标记的方法除了可以返回数组外,还可以返回一个Iterator,这样的好处是不用把所有的测试数据都加载到内存中,而是需要的时候就读一条。
下面的例子就使用了Iterator,然后在Iterator对象中保存了一个文件对象,在需要参数的时候就从文件中读一行数据出来。
这个例子主要由如下四个文件组成:

  1. Person类被测试类
  2. TxtIterator类实现Iterator接口,用于从文件中读取数据,返回给被测试类
  3. testng.xmlTestNG配置文件
  4. data.txt参数池文件

Person主类(被测试类)

package ngtest;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;

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

/**
 * @author Administrator
 *
 */
public class Person {

 String dataFile;

 @Parameters({ "file" })  //parameter可以添加在类的构造方法上
 public Person(String dataFile) {
  super();
  this.dataFile = dataFile;
 }

 @Test(dataProvider = "provider") //被测试方法
 public void getName(String name, String age) {
  System.out.println(name + "_" + age);
 }

 @DataProvider(name = "provider")
 public Iterator<String[]> provider() throws IOException {
  return new TxtIterator(new File(dataFile));
 }
}

TxtIterator类

package ngtest;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;

public class TxtIterator implements Iterator<String[]> {
 File txtFile;           //数据文件
 BufferedReader bs;
 String currentLine;

 public TxtIterator(File txtFile) throws IOException {
  super();
  this.txtFile = txtFile;
  try {
   bs = new BufferedReader(new FileReader(txtFile));
  } catch (FileNotFoundException e) {
   System.out.println("文件找不到");
   e.printStackTrace();
  }
  currentLine = bs.readLine();
 }

 @Override
 public boolean hasNext() {
  if (currentLine != null) {
   return true;
  } else {
   return false;
  }
 }

 @Override
 public String[] next() {
  String returnLine = currentLine;
  try {
   currentLine = bs.readLine();
  } catch (IOException e) {
   e.printStackTrace();
  }
  return returnLine.split(",");
 }

}

TestNG配置文件testng.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite">
 <parameter name="file" value="data.txt"/><!--数据文件的路径-->
 <test name="Test1">
  <classes>
   <class name="ngtest.Person" />
  </classes>
 </test>
</suite> 

数据文件data.txt

Liming,12
HanMeimei,13
Lily,11
Lucy,12

执行后输出

[TestNG] Running:
  D:\workspace\tester\testng.xml

Liming_12
HanMeimei_13
Lily_11
Lucy_12

===============================================
Suite
Total tests run: 4, Failures: 0, Skips: 0
===============================================

简单说一下上面的运行过程:

  1. 运行testng.xml,发现要运行的方法在Person类中,这就要构造一个Person类的对象,发现Person类的构造方法包含一个file参数,于是从testng.xml文件中把file参数的值取出来,传给了构造方法,创建了Person对象
  2. 开始执行测试,发现该测试方法需要一个DataProvider,于是在本类中找到了provider()方法,执行该方法,构造出Iterator对象,传递给测试方法。Iterator对象使用了Person对象中的dataFile成员变量的值构造出一个BufferedReader对象,每当测试方法需要一条数据时就由BufferedReader读一条数据出来,再拆分成数组,返回给测试方法调用。这样就实现了数据驱动和参数懒加载。