本系列所有代码 https://github.com/zhangting85/simpleWebtest
本文将介绍一个Java+TestNG+Maven+Selenium的web自动化测试脚本环境下testNG的Dataprovider的使用和数据驱动的自动化测试的实现,并提供全部代码。
首先,DataProvider是什么?
这是testNG提供的一个做数据驱动的自动化测试时用到的标签。详见testNG官网文档。
很多人会在使用testNG的时候把测试数据文件独立出来,有的人会自己去写读文件的方法,在测试方法里去调用。这样写不一定不好,但有时我们如果了解testNG提供的方法,就多了一种选择。而且通常DataProvider是比较好的一种选择。
DataProvider有两种写法:
一种是返回一个Iterator的泛型对象,代码如下:
1 package simplewebtest.test.testcases.sample.jd; 2 3 import java.util.ArrayList; 4 import java.util.Arrays; 5 import java.util.Iterator; 6 import java.util.List; 7 8 import org.testng.annotations.DataProvider; 9 import org.testng.annotations.Test; 10 11 import simplewebtest.core.TestCase; 12 import simplewebtest.core.page.sample.jd.JDHomepage; 13 14 public class TestJDDataDriven extends TestCase { 15 16 17 18 19 /** 20 * JD首页上搜索一个商品 主要介绍定位某个商品名称的N种写法 21 * 这里用了DataProvider 22 * (不会用DataProvier不要说自己懂testNG) 23 */ 24 @Test(dataProvider="product_to_search") 25 public void searchProduct(String keyword) throws InterruptedException { 26 27 log.info("keyword="+keyword); 28 //方法链。方法链并不会导致调试困难,因为我是先写线性脚本后重构成这种脚本this is a method chain 29 String actual_procut_name= new JDHomepage().init().searchHeader.search(keyword).getProductNameByIndexMethodTwo(1); 30 log.info("actual_procut_name="+actual_procut_name); 31 assert(actual_procut_name.contains(keyword)); 32 log.info("--------------------------------"); 33 } 34 35 /** 36 * 一个返回iterator的的DataProvider 37 */ 38 @DataProvider(name="product_to_search") 39 public Iterator<Object[]> createData1() { 40 //一个Array 41 String[] astringarray={"巧克力","饼","糕","蛋"}; 42 //转成一个String的List 43 List<String> lines=Arrays.asList(astringarray); 44 45 //一个Object的空的List 46 List<Object[]> data = new ArrayList<Object[]>(); 47 48 //往空List里放东西,然后返回 49 for (String line :lines ) 50 { 51 data.add(new Object[]{line}); 52 } 53 return data.iterator(); 54 55 } 56 57 }
另一种是返回一个Object的二维数组,代码如下:
1 package simplewebtest.test.testcases.sample.jd; 2 3 import org.testng.annotations.DataProvider; 4 import org.testng.annotations.Test; 5 6 import simplewebtest.core.TestCase; 7 import simplewebtest.core.page.sample.jd.JDHomepage; 8 9 public class TestJDDataDriven2 extends TestCase { 10 11 12 13 14 /** 15 * JD首页上搜索一个商品 主要介绍定位某个商品名称的N种写法 16 * 这里用了DataProvider 17 * (不会用DataProvier不要说自己懂testNG) 18 */ 19 @Test(dataProvider="product_to_search") 20 public void searchProduct(String keyword) throws InterruptedException { 21 22 log.info("keyword="+keyword); 23 String actual_procut_name= new JDHomepage().init().searchHeader.search(keyword).getProductNameByIndexMethodTwo(1); 24 log.info("actual_procut_name="+actual_procut_name); 25 assert(actual_procut_name.contains(keyword)); 26 log.info("--------------------------------"); 27 } 28 29 /** 30 * 一个返回Object2维数组的DataProvider 31 */ 32 @DataProvider(name="product_to_search") 33 public Object[][] createData1() { 34 return new Object[][] { 35 { "巧克力" }, 36 { "饼"}, 37 { "核桃"}, 38 }; 39 } 40 41 }
这两种写法都可以,随个人喜好选择吧。第二种方法更古老一点,在没有泛型的年代就只能用它了。
另外,DataProvider还支持并行执行。
比如,
@DataProvider(name="product_to_search",parallel = true)
parallel属性为true时,testNG会并行执行这个DataProvider提供的测试数据。
如此,我们的测试执行速度也会大幅提升(如果你的电脑有多个CPU,速度提升更明显)。下期介绍testNG中的并行测试执行时会给出例子。
有人问,我要把测试数据放到独立文件里去的话,怎么做?
这个问题其实很简单,我们仍旧使用DataProvider,在DataProvider里调用负责文件读取的方法,然后把文件内容存入我们DataProvider的返回值中。例子就不给了,请自己动手写吧。
但是呢,测试数据和测试用例分开放虽然有他的好处,新的问题却会产生:程序的读者(需要阅读或维护你代码的人)怎么知道哪个用例对应哪个数据?我亲眼见过有的人把上百个测试用例的数据放在一个txt文件里。其结构之混乱,对程序读者来说,无疑是一场灾难。请不要这么做!请在写代码时,考虑读者的感受,读者每次读到一个蹩脚的设计时是多么地难受啊。
有人问,我要把DataProvider独立到一个专门的类里去,行不行?
你可以自己试试哦,我记得是可以的。同样,请在做这种设计前考虑一下读者的感受,我不希望在一个巨大的包含几百个方法的类里寻找我用到的测试方法的DataProvider,请不要这么设计。
有人问,我一个DataProvider可不可以为多个测试方法提供数据?
完全可以哦,DataProvider上是可以跟一个传入参数Method的,用来表示调用这个DataProvider的方法名称。你可以在后续的代码里判断这个Method的值,根据不同的方法名为方法提供不同的数据。官网有例子哦,请看官网啊亲。或者自己试试写吧。这个系列里关于testNG的东西我就简单带过了,主要讲selenium嘛。