TestNG数据驱动简介

互联网 19-8-26
TestNG数据驱动

@DataProvider注解简介:

@DataProvider标记专门为测试方法提供参数的方法。这类方法必须返回Object[ ][ ]类型的二维数组或者Iterator<Object>[],每一行的Object[],都是测试方法的一个测试数据集,测试方法会为每个测试数据集执行一次。如果没有指定参数的名称,则默认为方法的名称,方法的名称没有限制。

@DataProvider的小例子:

import java.lang.reflect.Method; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class test {     @DataProvider(name = "user")     public Object[][] createUser(Method m) {         System.out.println(m.getName());         return new Object[][] { { "root", "root" }, { "test", "root" }, { "test", "test" } };     }     @Test(dataProvider = "user")     public void verifyUser(String username, String password) {         System.out.println("Verify User : " + username + ":" + password);         assert username.equals(password);     } }

如上所示@DataProvider注解了createUser方法,返回的二位数组里有三行数据,每行两列。

所以@Test(dataProvider = "user")注解的verifyUser方法有两个参数,用来接收每一行的两个数据,如果createUser返回的数据数组的列数和verifyUser的参数个数不同就会报错的。

因为返回的有三行,所以verifyUser会被执行三次。结果如下:

PASSED: verifyUser("root", "root") FAILED: verifyUser("test", "root") PASSED: verifyUser("test", "test")

CSV文件数据读取和@DataProvider

我自己做了一个以csv为例的测试架子,部分代码可通用。

CSV文件读取类(可通用,目录自己可以修改,也可改变成读取EXCEL、TXT等文件):

import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.regex.Matcher; public class CSVData implements Iterator<Object[]> {     private BufferedReader br        = null;     //行数     private int            rowNum    = 0;     //获取次数     private int            curRowNo  = 0;     //列数     private int            columnNum = 0;     //key名     private String[]       columnName;     //csv中所有行数据     private List<String>   csvList;     //实际想要的行数据     private List<String>   csvListNeed;     /*     * 在TestNG中由@DataProvider(dataProvider = "name")修饰的方法     * 取csv时,调用此类构造方法(此方法会得到列名并将当前行移到下以后)执行后,转发哦     * TestNG自己的方法中去,然后由它们调用此类实现的hasNext()、next()方法     * 得到一行数据,然后返回给由@Test(dataProvider = "name")修饰的方法,如此     * 反复到数据读完为止     *      *      * @param filepath CSV文件名     * @param casename 用例名     */     public CSVData(String fileName, String caseId) {         try {             File directory = new File(".");             String ss = "resources.";             File csv = new File(directory.getCanonicalFile() + "\\src\\test\\" + ss.replaceAll("\\.", Matcher.quoteReplacement("\\"))                                 + fileName + ".csv");             br = new BufferedReader(new FileReader(csv));             csvList = new ArrayList<String>();             while (br.ready()) {                 csvList.add(br.readLine());                 this.rowNum++;             }             String stringValue[] = csvList.get(0).split(",");             this.columnNum = stringValue.length;             columnName = new String[stringValue.length];             for (int i = 0; i < stringValue.length; i++) {                 columnName[i] = stringValue[i].toString();             }             this.curRowNo++;             csvListNeed = new ArrayList<String>();             for (int i = 1; i < rowNum; i++) {                 String values[] = csvList.get(i).split(",");                 if (caseId.equals(values[0])) {                     csvListNeed.add(csvList.get(i));                 }             }             this.rowNum = 2;//就取一行         } catch (Exception e) {             e.printStackTrace();         }     }     @Override     public boolean hasNext() {         if (this.rowNum == 0 || this.curRowNo >= this.rowNum) {             try {                 br.close();             } catch (Exception e) {                 e.printStackTrace();             }             return false;         } else {             return true;         }     }     @Override     public Object[] next() {         /*         * 将数据放入map          */         Map<String, String> s = new TreeMap<String, String>();         String csvCell[] = csvListNeed.get(0).split(",");         for (int i = 0; i < this.columnNum; i++) {             String temp = "";             try {                 temp = csvCell[i].toString();             } catch (ArrayIndexOutOfBoundsException ex) {                 temp = "";             }             s.put(this.columnName[i], temp);         }         Object r[] = new Object[1];         r[0] = s;         this.curRowNo++;         return r;     }     @Override     public void remove() {         throw new UnsupportedOperationException("remove unsupported");     } }

这个类实现了Iterator<Object[]>迭代器,TestNG调用此类实现的hasNext()、next()方法得到一行数据,在next()方法中可以看到,我把数据是放在Map<String, String>中的,再把map放在Object[]里,所以测试方法的参数就必须是一个Map<String, String>。我这里改成了只读取一行,因为一个csv文件的一个caseId只应该有一行。

数据驱动类:

import java.lang.reflect.Method; import java.util.Iterator; import org.testng.annotations.DataProvider; public class DataProviderTest {     /**      * @DataProvider的返回值类型只能是Object[][]与Iterator<Object>[]      *       * @param method      * @return      */     @DataProvider     public Iterator<Object[]> dataSource(Method method) {         return (Iterator<Object[]>) new CSVData(method.getDeclaringClass().getSimpleName(), method.getName());     } }

Method方法是通过反射获取的,总之哪个方法调用我Method就是那个方法。

method.getDeclaringClass().getSimpleName()可以获取方法所属的类的类名。

我这里规定了csv的文件名就是测试类的类名,用例名就是方法名。

return (Iterator<Object[]>) new CSVData(…)就是将CSV读取类读取的结果返回,返回的类型是Iterator<Object[]>的,符合@DataProvider的返回值类型要求。当@Test(dataProvider = "dataSource")注解的测试方法执行时就会调用Iterator的hasNext()判断是否有数据和next()获取数据。

测试类:

import java.util.Map; import org.testng.annotations.Test; public class DataTest extends DataProviderTest {     @Test(dataProvider = "dataSource")     public void id2(Map<String, String> data) {         System.out.println(data);     }     @Test(dataProvider = "dataSource")     public void id1(Map<String, String> data) {         System.out.println(data);     } }

输出结果如下:

PASSED: id1({caseId=id1, flag=Y, property=flowModel, type=com.mybank.bkloanapply.core.model.BaseModel, value=BaseModel.csv@1}) PASSED: id2({caseId=id2, flag=M, property=context, type=java.util.Map, value=a:Object.csv@1})

总结

通过以上例子可以看到,无论@DataProvider注解的方法返回的是Object[ ][ ]还是Iterator<Object>[],最后测试方法获得的参数都是Object[ ]里放的东西,第一个例子里放了两列String,第二个例子里放了Map<String, String>,所以第一个测试类的测试方法的参数是两个String,第二个测试类的测试方法的参数是Map<String, String>,必须保持一致才行。

以上就是TestNG数据驱动简介的详细内容,更多内容请关注技术你好其它相关文章!

来源链接:
免责声明:
1.资讯内容不构成投资建议,投资者应独立决策并自行承担风险
2.本文版权归属原作所有,仅代表作者本人观点,不代表本站的观点或立场
标签: java
上一篇:php获取远程图片并下载保存到本地的方法分析 下一篇:eclipse导入后怎么运行

相关资讯