溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

java中TestNG數(shù)據(jù)驅(qū)動(dòng)是什么

發(fā)布時(shí)間:2020-11-09 14:26:33 來源:億速云 閱讀:181 作者:小新 欄目:編程語言

這篇文章給大家分享的是有關(guān)java中TestNG數(shù)據(jù)驅(qū)動(dòng)是什么的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考。一起跟隨小編過來看看吧。

TestNG數(shù)據(jù)驅(qū)動(dòng)

testng的功能很強(qiáng)大,利用@DataProvider可以做數(shù)據(jù)驅(qū)動(dòng),數(shù)據(jù)源文件可以是EXCEL,XML,YAML,甚至可以是TXT文本。

@DataProvider注解簡(jiǎn)介:

@DataProvider標(biāo)記專門為測(cè)試方法提供參數(shù)的方法。這類方法必須返回Object[ ][ ]類型的二維數(shù)組或者Iterator<Object>[],每一行的Object[],都是測(cè)試方法的一個(gè)測(cè)試數(shù)據(jù)集,測(cè)試方法會(huì)為每個(gè)測(cè)試數(shù)據(jù)集執(zhí)行一次。如果沒有指定參數(shù)的名稱,則默認(rèn)為方法的名稱,方法的名稱沒有限制。

@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方法,返回的二位數(shù)組里有三行數(shù)據(jù),每行兩列。

所以@Test(dataProvider = "user")注解的verifyUser方法有兩個(gè)參數(shù),用來接收每一行的兩個(gè)數(shù)據(jù),如果createUser返回的數(shù)據(jù)數(shù)組的列數(shù)和verifyUser的參數(shù)個(gè)數(shù)不同就會(huì)報(bào)錯(cuò)的。

因?yàn)榉祷氐挠腥校詖erifyUser會(huì)被執(zhí)行三次。結(jié)果如下:

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

CSV文件數(shù)據(jù)讀取和@DataProvider

我自己做了一個(gè)以csv為例的測(cè)試架子,部分代碼可通用。

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;
    //行數(shù)
    private int            rowNum    = 0;
    //獲取次數(shù)
    private int            curRowNo  = 0;
    //列數(shù)
    private int            columnNum = 0;
    //key名
    private String[]       columnName;
    //csv中所有行數(shù)據(jù)
    private List<String>   csvList;
    //實(shí)際想要的行數(shù)據(jù)
    private List<String>   csvListNeed;
    /*
    * 在TestNG中由@DataProvider(dataProvider = "name")修飾的方法
    * 取csv時(shí),調(diào)用此類構(gòu)造方法(此方法會(huì)得到列名并將當(dāng)前行移到下以后)執(zhí)行后,轉(zhuǎn)發(fā)哦
    * TestNG自己的方法中去,然后由它們調(diào)用此類實(shí)現(xiàn)的hasNext()、next()方法
    * 得到一行數(shù)據(jù),然后返回給由@Test(dataProvider = "name")修飾的方法,如此
    * 反復(fù)到數(shù)據(jù)讀完為止
    * 
    * 
    * @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() {
        /*
        * 將數(shù)據(jù)放入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");
    }
}

這個(gè)類實(shí)現(xiàn)了Iterator<Object[]>迭代器,TestNG調(diào)用此類實(shí)現(xiàn)的hasNext()、next()方法得到一行數(shù)據(jù),在next()方法中可以看到,我把數(shù)據(jù)是放在Map<String, String>中的,再把map放在Object[]里,所以測(cè)試方法的參數(shù)就必須是一個(gè)Map<String, String>。我這里改成了只讀取一行,因?yàn)橐粋€(gè)csv文件的一個(gè)caseId只應(yīng)該有一行。

數(shù)據(jù)驅(qū)動(dòng)類:

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方法是通過反射獲取的,總之哪個(gè)方法調(diào)用我Method就是那個(gè)方法。

method.getDeclaringClass().getSimpleName()可以獲取方法所屬的類的類名。

我這里規(guī)定了csv的文件名就是測(cè)試類的類名,用例名就是方法名。

return (Iterator<Object[]>) new CSVData(…)就是將CSV讀取類讀取的結(jié)果返回,返回的類型是Iterator<Object[]>的,符合@DataProvider的返回值類型要求。當(dāng)@Test(dataProvider = "dataSource")注解的測(cè)試方法執(zhí)行時(shí)就會(huì)調(diào)用Iterator的hasNext()判斷是否有數(shù)據(jù)和next()獲取數(shù)據(jù)。

測(cè)試類:

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);
    }
}

輸出結(jié)果如下:

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})

總結(jié)

通過以上例子可以看到,無論@DataProvider注解的方法返回的是Object[ ][ ]還是Iterator<Object>[],最后測(cè)試方法獲得的參數(shù)都是Object[ ]里放的東西,第一個(gè)例子里放了兩列String,第二個(gè)例子里放了Map<String, String>,所以第一個(gè)測(cè)試類的測(cè)試方法的參數(shù)是兩個(gè)String,第二個(gè)測(cè)試類的測(cè)試方法的參數(shù)是Map<String, String>,必須保持一致才行。

感謝各位的閱讀!關(guān)于java中TestNG數(shù)據(jù)驅(qū)動(dòng)是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI