• 技术文章 >Java >java教程

    TestNG数据驱动简介

    (*-*)浩(*-*)浩2019-08-26 16:19:02转载1216
    TestNG数据驱动

    testng的功能很强大,利用@DataProvider可以做数据驱动,数据源文件可以是EXCEL,XML,YAML,甚至可以是TXT文本。

    php入门到就业线上直播课:进入学习

    @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数据驱动简介的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:CSDN,如有侵犯,请联系admin@php.cn删除

    前端(VUE)零基础到就业课程:点击学习

    清晰的学习路线+老师随时辅导答疑

    自己动手写 PHP MVC 框架:点击学习

    快速了解MVC架构、了解框架底层运行原理

    专题推荐:java
    上一篇:eclipse导入后怎么运行 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• python和java学哪个• java的三大特性封装、继承、多态• 提高java代码的重用性• java常见字符串操作
    1/1

    PHP中文网