手把手教你搭建數(shù)據(jù)驅(qū)動(dòng)測試框架

前言

在自動(dòng)化測試框架中闭专,數(shù)據(jù)驅(qū)動(dòng)的意思指定的是測試用例或者說測試套件是由外部數(shù)據(jù)集合來驅(qū)動(dòng)的框架拨扶。這里說的數(shù)據(jù)集可以是任何類型的數(shù)據(jù)文件比如xls,xlsx呼巴,csv等等泽腮。它的核心的思想就是數(shù)據(jù)和測試代碼分離,及時(shí)當(dāng)測試數(shù)據(jù)發(fā)生大量變化的情況下測試代碼(或者說測試用例)可以保持不變衣赶。數(shù)據(jù)集合里有1條數(shù)據(jù)和100條甚至更多诊赊,是不會(huì)影響到測試用例的執(zhí)行。如果想使用一組不同的數(shù)據(jù)來執(zhí)行的相同的操作沒那么你就可以選擇數(shù)據(jù)驅(qū)動(dòng)府瞄。

比如碧磅,在這么一種場景下,例如你需要用多個(gè)不同的賬號(hào)和密碼來登陸某個(gè)郵箱遵馆,來驗(yàn)證哪些是有效的值鲸郊,哪些是錯(cuò)誤的值,或者哪些值可以導(dǎo)致出錯(cuò)货邓,這只是一個(gè)簡單的例子秆撮。另外一個(gè)簡單的例子就是網(wǎng)絡(luò)電話的測試,當(dāng)我們模擬撥號(hào)换况、掛斷职辨、回?fù)艿鹊炔僮鲿r(shí)我們希望驗(yàn)證每個(gè)按鈕是否能正常工作并能得到正確的結(jié)果盗蟆。

本篇文章是基于Selenium WebDriver的數(shù)據(jù)驅(qū)動(dòng)測試框架,如果大家跟著一步一步搭建下來舒裤,最終的框架將最終實(shí)現(xiàn)下面的這些功能:

1姆涩、可以在測試套件列表里設(shè)置指定的測試套件是否執(zhí)行

2、可以在測試用例列表里設(shè)置指定的測試用例是否執(zhí)行

3惭每、可以在測試數(shù)據(jù)表里設(shè)置某行測試數(shù)據(jù)是否被讀取執(zhí)行

4骨饿、一個(gè)測試用例可以由多個(gè)測試數(shù)據(jù)驅(qū)動(dòng)運(yùn)行

5、可以打印測試結(jié)果報(bào)告台腥,顯示指定數(shù)據(jù)行執(zhí)行之后的結(jié)果

6宏赘、可以打印整體測試結(jié)果報(bào)告,顯示哪些用例執(zhí)行通過黎侈,哪些執(zhí)行失敗察署、哪些跳過沒執(zhí)行

7、報(bào)告可以是testng的形式或者是XSLT

接下來的過程中不會(huì)講太多理論的東西峻汉,更注重于實(shí)踐的步驟贴汪,我將一步一步的介紹如何搭建這個(gè)框架,演示總個(gè)過程休吠。

一扳埂、搭建

1、創(chuàng)建工作空間

按照下面步驟在創(chuàng)建 項(xiàng)目工作空間

1.在F盤下創(chuàng)建文件夾backup

2.在backup文件夾下創(chuàng)建Training文件夾

創(chuàng)建完畢就有這樣的目錄結(jié)構(gòu)F:\backup\Training瘤礁。然后打開eclipse阳懂,選擇上面創(chuàng)建的文件夾為工作空間,如下圖所示:

2柜思、創(chuàng)建項(xiàng)目

創(chuàng)建一個(gè)名為WDDF的項(xiàng)目岩调,我們將使用這個(gè)項(xiàng)目來搭建我們的測試框架,創(chuàng)建完畢赡盘,包結(jié)構(gòu)如圖所示:

3号枕、創(chuàng)建項(xiàng)目的目錄結(jié)構(gòu)

創(chuàng)建項(xiàng)目目錄結(jié)構(gòu)也就是在項(xiàng)目下創(chuàng)建需要的包和文件夾結(jié)構(gòu)。包結(jié)構(gòu)合理就很容易對(duì)項(xiàng)目的資源進(jìn)行管理而不胡亂陨享。在“WDDF”項(xiàng)目下創(chuàng)建如下包:

com.stta.ExcelFiles: --存放.xsl文件

com.stta.Logging: --存放.log文件

com.stta.property: --存放.property文件

com.stta.SuiteOne: --存放測試套件一相關(guān)文件

com.stta.SuiteTwo: --存放測試套件二相關(guān)文件

com.stta.TestSuiteBase: --存放基本類文件

com.stta.utility: --存放工具類文件

com.stta.xslt: --存放testng-results.xsl文件

同時(shí)創(chuàng)建文件夾:

1.JarFiles: --存放所有需要的相關(guān)的jar文件

到此葱淳,項(xiàng)目結(jié)構(gòu)就如下圖所示:

針對(duì)不同的文件類型創(chuàng)建分離的包的是由好處的,這樣子可以在我們查找霉咨、修改文件的時(shí)候很便利蛙紫,例如你要修稿.xls文件的數(shù)據(jù),那么你幾可以直接在com.stta.ExcelFiles包里面找途戒,同樣的你想查看執(zhí)行的日志坑傅,就可以直接在com.stta.Logging里面查看,非常直觀喷斋。

好了唁毒,到此為止蒜茴,可以說我們項(xiàng)目的基本初始化工作基本完成。

二浆西、下載需要的Jar包

現(xiàn)在項(xiàng)目結(jié)構(gòu)都創(chuàng)建好粉私,接下來要做的就是下載所有用到的Jar包。這里我會(huì)羅列所有需要下載jar包近零。并一個(gè)個(gè)下載下來保存到JarFiles文件夾下诺核。

1、Apache POI API

Apache POI API是用來從.xls文件中寫入或者讀取數(shù)據(jù)用的久信,所以必須下載Apache POI API和它依賴相關(guān)的jar包窖杀,并設(shè)置它門在build path中,我們才能使用它裙士。

Apache POI API可以在它的官網(wǎng)直接下載入客。進(jìn)去后點(diǎn)擊“poi-bin-3.10-FINAL-20140208.tar.gz”。下載完畢后解壓腿椎,解壓目錄下和子目錄里面的下列文件拷貝到“WDDF"項(xiàng)目的JarFiles文件夾下:

poi-3.10-FINAL-20140208.jar

poi-ooxml-3.10-FINAL-20140208.jar

poi-ooxml-schemas-3.10-FINAL-20140208.jar

xmlbeans-2.3.0.jar (在子目錄 ooxml-lib 下)

dom4j-1.6.1.jar (在子目錄 ooxml-lib 下)

2桌硫、Apache log4j

Apache log4j 是用來記錄測試執(zhí)行期間產(chǎn)生的日志的,我們也需要把它加到build path中啃炸。從Apache log4j主頁下載Apache log4j jar文件铆隘,并拷貝到“WDDF"項(xiàng)目的JarFiles文件夾下:

log4j-1.2.17.jar

3、Selenium WebDriver

如果你使用過Selenium WebDriver肮帐,估計(jì)就知道使用selenium webdriver需要下載那些jar包了咖驮。從Selenium WebDriver主頁下載Selenium WebDriver的zip包,解壓训枢,并把"selenium-x.xx.x"目錄和它的子目錄“l(fā)ibs”下的所有jar文件拷貝到“WDDF"項(xiàng)目的JarFiles文件夾下。

與生成XSLT報(bào)告相關(guān)的jar

為了能夠產(chǎn)生交互式的測試報(bào)告忘巧,我們還需要一些工具的支持恒界。到這個(gè)頁面下載一個(gè)zip包。解壓砚嘴,并把"testng-xslt-1.1.2-master" -> "lib" 下的下列文件拷貝到“WDDF"項(xiàng)目的JarFiles文件夾下:

saxon-8.7.jar

三十酣、與生成XSLT報(bào)告相關(guān)的jar

拷貝 “testng-xslt-1.1.2-master\src\main\resources"目錄下的testng-results.xsl文件到包c(diǎn)om.stta.xslt下面。

testng-results.xsl

到此為止际长,我們的JarFile目錄和com.stta.xslt包看起來如下圖所示:

四耸采、配置環(huán)境

本框架中,我們使用Apache POI API 來從.xls 中讀取數(shù)據(jù)工育,Apache log4j來記錄測試執(zhí)行過程中產(chǎn)生的日志虾宇,而xslt 報(bào)告用來產(chǎn)生交互式HTML報(bào)告。下載完相關(guān)的jar包后如绸,我們就需要把他們加到 項(xiàng)目的build path中嘱朽。

1.選擇郵件點(diǎn)擊項(xiàng)目 WDDF旭贬,選擇 "Build Path" -> "Configure Build Path"

2.點(diǎn)擊Libraries->Add external JARs

3.選擇上述下載的所有jar包,點(diǎn)添加->OK

這樣所有jar就添加到build path中了搪泳。查看一下eclipse稀轨,會(huì)多了一個(gè)“Referenced Libraries”,Referenced Libraries下包含所有所需 的jar包:

五岸军、創(chuàng)建類文件

1奋刽、創(chuàng)建基類

com.stta.TestSuiteBase下創(chuàng)建SuiteBase.java,這個(gè)類用于總個(gè)框架測試套件的基類

1.SuiteBase.java

com.stta.SuiteOne這個(gè)包用來存放測試套件一的相關(guān)的類艰赞,創(chuàng)建如下類:

SuiteOneBase.java ---這個(gè)類用于測試套件一的基類

SuiteOneCaseOne.java ---這個(gè)為測試套件一的用例一

SuiteOneCaseOne.java ---這個(gè)為測試套件二的用例二

com.stta.SuiteTwo 這個(gè)包用來存放測試套件二相關(guān)的類杨名,創(chuàng)建如下類:

SuiteTwoBase.java

SuiteTwoCaseOne.java

SuiteTwoCaseTwo.java

com.stta.utility 包作為測試框架的基本工具包,創(chuàng)建如下兩個(gè)類:

Read_XLS.java ---讀取.xls文件相關(guān)更能的類

SuiteUtility.java ---工具類

創(chuàng)建完畢猖毫,目錄結(jié)構(gòu)如圖所示:

?2台谍、創(chuàng)建xls文件

為了簡單起見,這次搭建的測試框架只支持.xls文件吁断,通過檢索.xls文件趁蕊,測試框架可以獲取要測試套件名稱、是否執(zhí)行的標(biāo)志仔役,測試用例的名稱以及是否執(zhí)行用例的標(biāo)志位掷伙,而且等測試執(zhí)行完畢,可以把測試結(jié)果.xls文件的末尾∮直現(xiàn)在先創(chuàng)建如三個(gè).xls文件:

TestSuiteList.xls

SuiteOne.xls

SuiteTwo.xls

創(chuàng)建完任柜,com.stta.ExcelFiles看起來像下面的樣子:

下面講下這三個(gè).xls文件怎么創(chuàng)建:

1、TestSuiteList.xls

TestSuiteList.xls文件只有第一個(gè)sheet有數(shù)據(jù)沛厨,把第一個(gè)sheet命名為SuitesList,SuitesListl里面有三列分別是SuiteName宙地、SuiteToRun、Skipped/Executed 如圖:

2逆皮、SuiteOne.xls與SuiteTwo.xls

這兩文件里面的表格是一致的宅粥,就放在一起說明,這兩個(gè).xls文件有三個(gè)sheet电谣,第一個(gè)是TestCasesList秽梅,測試用例列表,指明本測試套有幾個(gè)測試用例剿牺。第二和第三個(gè)sheet名稱分別是SuiteOneCaseOne和SuiteOneCaseTwo企垦,分別是測試用例一個(gè)測試用例二的測試數(shù)據(jù)。TestCasesList如下圖所示晒来,表格也是有三列钞诡,分別表示測試用例名稱、是否執(zhí)行、和執(zhí)行結(jié)果 三個(gè)

SuiteOneCaseOne和SuiteOneCaseTwo的表格結(jié)構(gòu)如下圖所示:

記住一個(gè)原則臭增,如下圖所示懂酱,即eclipse里從測試類的名稱、TestCasesList表的測試用例名稱和測試用例數(shù)據(jù)的sheet名稱這個(gè)三個(gè)要保持一致誊抛。后續(xù)增加任何的測試用例都要遵循這個(gè)原則列牺。

六、開始寫代碼

前面把要用掉的類文件先創(chuàng)建起來了拗窃,需要的用到的文件也都準(zhǔn)備好了瞎领,可以開始寫代碼了。首先先寫框架的工具類來讀取數(shù)據(jù)随夸,因?yàn)檫@些工具類在其他類中頻繁用到先寫九默。

Read_XLS.java代碼如下

package com.stta.utility;

import java.io.FileInputStream;

import java.io.FileOutputStream;

//import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFCell;

import org.apache.poi.hssf.usermodel.HSSFRow;

import org.apache.poi.hssf.usermodel.HSSFSheet;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import org.apache.poi.ss.usermodel.*;

public class Read_XLS {

? ? public? String filelocation;

? ? public? FileInputStream ipstr = null;

? ? public? FileOutputStream opstr =null;

? ? private HSSFWorkbook wb = null;

? ? private HSSFSheet ws = null;? ?


? ? public Read_XLS(String filelocation) {? ? ?

? ? ? ? this.filelocation=filelocation;

? ? ? ? try {

? ? ? ? ? ? ipstr = new FileInputStream(filelocation);

? ? ? ? ? ? wb = new HSSFWorkbook(ipstr);

? ? ? ? ? ? ws = wb.getSheetAt(0);

? ? ? ? ? ? ipstr.close();

? ? ? ? } catch (Exception e) {? ? ? ?

? ? ? ? ? ? e.printStackTrace();

? ? ? ? }


? ? }


? ? //檢索 .xls 文件 sheets的行數(shù).

? ? public int retrieveNoOfRows(String wsName){? ?

? ? ? ? int sheetIndex=wb.getSheetIndex(wsName);

? ? ? ? if(sheetIndex==-1)

? ? ? ? ? ? return 0;

? ? ? ? else{

? ? ? ? ? ? ws = wb.getSheetAt(sheetIndex);

? ? ? ? ? ? int rowCount=ws.getLastRowNum()+1;? ? ?

? ? ? ? ? ? return rowCount;? ? ? ?

? ? ? ? }

? ? }


? ? //檢索.xls文件sheets的列數(shù)

? ? public int retrieveNoOfCols(String wsName){

? ? ? ? int sheetIndex=wb.getSheetIndex(wsName);

? ? ? ? if(sheetIndex==-1)

? ? ? ? ? ? return 0;

? ? ? ? else{

? ? ? ? ? ? ws = wb.getSheetAt(sheetIndex);

? ? ? ? ? ? int colCount=ws.getRow(0).getLastCellNum();? ? ? ?

? ? ? ? ? ? return colCount;

? ? ? ? }

? ? }


? ? //讀取測試套件和測試用例的SuiteToRun and CaseToRun標(biāo)志

? ? public String retrieveToRunFlag(String wsName, String colName, String rowName){


? ? ? ? int sheetIndex=wb.getSheetIndex(wsName);

? ? ? ? if(sheetIndex==-1)

? ? ? ? ? ? return null;

? ? ? ? else{

? ? ? ? ? ? int rowNum = retrieveNoOfRows(wsName);

? ? ? ? ? ? int colNum = retrieveNoOfCols(wsName);

? ? ? ? ? ? int colNumber=-1;

? ? ? ? ? ? int rowNumber=-1;? ? ? ? ?


? ? ? ? ? ? HSSFRow Suiterow = ws.getRow(0);? ? ? ? ? ? ? ?


? ? ? ? ? ? for(int i=0; i<colNum; i++){

? ? ? ? ? ? ? ? if(Suiterow.getCell(i).getStringCellValue().equals(colName.trim())){

? ? ? ? ? ? ? ? ? ? colNumber=i;? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ?

? ? ? ? ? ? }


? ? ? ? ? ? if(colNumber==-1){

? ? ? ? ? ? ? ? return "";? ? ? ? ? ? ?

? ? ? ? ? ? }



? ? ? ? ? ? for(int j=0; j<rowNum; j++){

? ? ? ? ? ? ? ? HSSFRow Suitecol = ws.getRow(j);? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? if(Suitecol.getCell(0).getStringCellValue().equals(rowName.trim())){

? ? ? ? ? ? ? ? ? ? rowNumber=j;? ?

? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ?

? ? ? ? ? ? }


? ? ? ? ? ? if(rowNumber==-1){

? ? ? ? ? ? ? ? return "";? ? ? ? ? ? ?

? ? ? ? ? ? }


? ? ? ? ? ? HSSFRow row = ws.getRow(rowNumber);

? ? ? ? ? ? HSSFCell cell = row.getCell(colNumber);

? ? ? ? ? ? if(cell==null){

? ? ? ? ? ? ? ? return "";

? ? ? ? ? ? }

? ? ? ? ? ? String value = cellToString(cell);

? ? ? ? ? ? return value;? ? ? ? ?

? ? ? ? }? ? ? ? ?

? ? }


? ? //讀取測試數(shù)據(jù)的DataToRun標(biāo)志.

? ? public String[] retrieveToRunFlagTestData(String wsName, String colName){


? ? ? ? int sheetIndex=wb.getSheetIndex(wsName);

? ? ? ? if(sheetIndex==-1)

? ? ? ? ? ? return null;

? ? ? ? else{

? ? ? ? ? ? int rowNum = retrieveNoOfRows(wsName);

? ? ? ? ? ? int colNum = retrieveNoOfCols(wsName);

? ? ? ? ? ? int colNumber=-1;



? ? ? ? ? ? HSSFRow Suiterow = ws.getRow(0);? ? ? ? ? ? ? ?

? ? ? ? ? ? String data[] = new String[rowNum-1];

? ? ? ? ? ? for(int i=0; i<colNum; i++){

? ? ? ? ? ? ? ? if(Suiterow.getCell(i).getStringCellValue().equals(colName.trim())){

? ? ? ? ? ? ? ? ? ? colNumber=i;? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ?

? ? ? ? ? ? }


? ? ? ? ? ? if(colNumber==-1){

? ? ? ? ? ? ? ? return null;? ? ? ? ? ? ? ?

? ? ? ? ? ? }


? ? ? ? ? ? for(int j=0; j<rowNum-1; j++){

? ? ? ? ? ? ? ? HSSFRow Row = ws.getRow(j+1);

? ? ? ? ? ? ? ? if(Row==null){

? ? ? ? ? ? ? ? ? ? data[j] = "";

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? else{

? ? ? ? ? ? ? ? ? ? HSSFCell cell = Row.getCell(colNumber);

? ? ? ? ? ? ? ? ? ? if(cell==null){

? ? ? ? ? ? ? ? ? ? ? ? data[j] = "";

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? else{

? ? ? ? ? ? ? ? ? ? ? ? String value = cellToString(cell);

? ? ? ? ? ? ? ? ? ? ? ? data[j] = value;? ?

? ? ? ? ? ? ? ? ? ? }?

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }


? ? ? ? ? ? return data;? ? ? ? ? ?

? ? ? ? }? ? ? ? ?

? ? }


? ? //從測試用例數(shù)據(jù)sheets讀取測試數(shù)據(jù).

? ? public Object[][] retrieveTestData(String wsName){

? ? ? ? int sheetIndex=wb.getSheetIndex(wsName);

? ? ? ? if(sheetIndex==-1)

? ? ? ? ? ? return null;

? ? ? ? else{

? ? ? ? ? ? ? ? int rowNum = retrieveNoOfRows(wsName);

? ? ? ? ? ? ? ? int colNum = retrieveNoOfCols(wsName);


? ? ? ? ? ? ? ? Object data[][] = new Object[rowNum-1][colNum-2];


? ? ? ? ? ? ? ? for (int i=0; i<rowNum-1; i++){

? ? ? ? ? ? ? ? ? ? HSSFRow row = ws.getRow(i+1);

? ? ? ? ? ? ? ? ? ? for(int j=0; j< colNum-2; j++){? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? if(row==null){

? ? ? ? ? ? ? ? ? ? ? ? ? ? data[i][j] = "";

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? else{

? ? ? ? ? ? ? ? ? ? ? ? ? ? HSSFCell cell = row.getCell(j);


? ? ? ? ? ? ? ? ? ? ? ? ? ? if(cell==null){

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? data[i][j] = "";? ? ? ? ? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? ? ? else{

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? cell.setCellType(Cell.CELL_TYPE_STRING);

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? String value = cellToString(cell);

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? data[i][j] = value;? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ?

? ? ? ? ? ? ? ? }? ? ? ? ?

? ? ? ? ? ? ? ? return data;? ? ? ?

? ? ? ? }


? ? }? ? ?



? ? public static String cellToString(HSSFCell cell){

? ? ? ? int type;

? ? ? ? Object result;

? ? ? ? type = cell.getCellType();? ? ? ? ?

? ? ? ? switch (type){

? ? ? ? ? ? case 0 :

? ? ? ? ? ? ? ? result = cell.getNumericCellValue();

? ? ? ? ? ? ? ? break;


? ? ? ? ? ? case 1 :

? ? ? ? ? ? ? ? result = cell.getStringCellValue();

? ? ? ? ? ? ? ? break;


? ? ? ? ? ? default :

? ? ? ? ? ? ? ? throw new RuntimeException("Unsupportd cell.");? ? ? ?

? ? ? ? }

? ? ? ? return result.toString();

? ? }


? ? //在測試數(shù)據(jù)和測試用例表里寫入測試結(jié)果

? ? public boolean writeResult(String wsName, String colName, int rowNumber, String Result){

? ? ? ? try{

? ? ? ? ? ? int sheetIndex=wb.getSheetIndex(wsName);

? ? ? ? ? ? if(sheetIndex==-1)

? ? ? ? ? ? ? ? return false;? ? ? ? ?

? ? ? ? ? ? int colNum = retrieveNoOfCols(wsName);

? ? ? ? ? ? int colNumber=-1;



? ? ? ? ? ? HSSFRow Suiterow = ws.getRow(0);? ? ? ? ? ?

? ? ? ? ? ? for(int i=0; i<colNum; i++){? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? if(Suiterow.getCell(i).getStringCellValue().equals(colName.trim())){

? ? ? ? ? ? ? ? ? ? colNumber=i;? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ?

? ? ? ? ? ? }


? ? ? ? ? ? if(colNumber==-1){

? ? ? ? ? ? ? ? return false;? ? ? ? ? ? ?

? ? ? ? ? ? }


? ? ? ? ? ? HSSFRow Row = ws.getRow(rowNumber);

? ? ? ? ? ? HSSFCell cell = Row.getCell(colNumber);

? ? ? ? ? ? if (cell == null)

? ? ? ? ? ? ? ? cell = Row.createCell(colNumber);? ? ? ? ?


? ? ? ? ? ? cell.setCellValue(Result);


? ? ? ? ? ? opstr = new FileOutputStream(filelocation);

? ? ? ? ? ? wb.write(opstr);

? ? ? ? ? ? opstr.close();



? ? ? ? }catch(Exception e){

? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? return false;

? ? ? ? }

? ? ? ? return true;

? ? }


? ? //在測試套件表里寫入測試結(jié)果.

? ? public boolean writeResult(String wsName, String colName, String rowName, String Result){

? ? ? ? try{

? ? ? ? ? ? int rowNum = retrieveNoOfRows(wsName);

? ? ? ? ? ? int rowNumber=-1;

? ? ? ? ? ? int sheetIndex=wb.getSheetIndex(wsName);

? ? ? ? ? ? if(sheetIndex==-1)

? ? ? ? ? ? ? ? return false;? ? ? ? ?

? ? ? ? ? ? int colNum = retrieveNoOfCols(wsName);

? ? ? ? ? ? int colNumber=-1;



? ? ? ? ? ? HSSFRow Suiterow = ws.getRow(0);? ? ? ? ? ?

? ? ? ? ? ? for(int i=0; i<colNum; i++){? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? if(Suiterow.getCell(i).getStringCellValue().equals(colName.trim())){

? ? ? ? ? ? ? ? ? ? colNumber=i;? ? ? ? ? ? ? ? ? ?

? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ?

? ? ? ? ? ? }


? ? ? ? ? ? if(colNumber==-1){

? ? ? ? ? ? ? ? return false;? ? ? ? ? ? ?

? ? ? ? ? ? }


? ? ? ? ? ? for (int i=0; i<rowNum-1; i++){

? ? ? ? ? ? ? ? HSSFRow row = ws.getRow(i+1);? ? ? ? ? ? ?

? ? ? ? ? ? ? ? HSSFCell cell = row.getCell(0);

? ? ? ? ? ? ? ? cell.setCellType(Cell.CELL_TYPE_STRING);

? ? ? ? ? ? ? ? String value = cellToString(cell);?

? ? ? ? ? ? ? ? if(value.equals(rowName)){

? ? ? ? ? ? ? ? ? ? rowNumber=i+1;

? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }? ? ?


? ? ? ? ? ? HSSFRow Row = ws.getRow(rowNumber);

? ? ? ? ? ? HSSFCell cell = Row.getCell(colNumber);

? ? ? ? ? ? if (cell == null)

? ? ? ? ? ? ? ? cell = Row.createCell(colNumber);? ? ? ? ?


? ? ? ? ? ? cell.setCellValue(Result);


? ? ? ? ? ? opstr = new FileOutputStream(filelocation);

? ? ? ? ? ? wb.write(opstr);

? ? ? ? ? ? opstr.close();



? ? ? ? }catch(Exception e){

? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? return false;

? ? ? ? }

? ? ? ? return true;

? ? }

}

SuiteUtility.java代碼:

package com.stta.utility;

public class SuiteUtility {

public static boolean checkToRunUtility(Read_XLS xls, String sheetName, String ToRun, String testSuite){


? ? boolean Flag = false;? ? ?

? ? if(xls.retrieveToRunFlag(sheetName,ToRun,testSuite).equalsIgnoreCase("y")){

? ? ? ? Flag = true;

? ? }

? ? else{

? ? ? ? Flag = false;

? ? }

? ? return Flag;? ? ? ?

}

public static String[] checkToRunUtilityOfData(Read_XLS xls, String sheetName, String ColName){? ?

? ? return xls.retrieveToRunFlagTestData(sheetName,ColName);? ? ? ? ? ?

}

public static Object[][] GetTestDataUtility(Read_XLS xls, String sheetName){

? ? return xls.retrieveTestData(sheetName);

}

public static boolean WriteResultUtility(Read_XLS xls, String sheetName, String ColName, int rowNum, String Result){? ? ? ? ? ?

? ? return xls.writeResult(sheetName, ColName, rowNum, Result);? ? ? ?

}

public static boolean WriteResultUtility(Read_XLS xls, String sheetName, String ColName, String rowName, String Result){? ? ? ? ? ?

? ? return xls.writeResult(sheetName, ColName, rowName, Result);? ? ? ? ? ?

}

}

七、簡單數(shù)據(jù)讀取測試

測試框架的.xls文件讀取工具已經(jīng)準(zhǔn)備好宾毒,按照前面創(chuàng)建的測試類驼修,我們要?jiǎng)?chuàng)建兩個(gè)測試套件,每個(gè)測試套件有兩個(gè)測試用例诈铛,總共就是2個(gè)測試套件和4個(gè)測試用例乙各。對(duì)于每個(gè)測試套件分別對(duì)應(yīng)兩個(gè)不同.xls文件。測試套件幢竹、測試用例與.xls文件之間的映射關(guān)系如下所示:

com.stta.SuiteOne -> SuiteOne.xls

SuiteOneCaseOne.java -> SuiteOneCaseOne Sheet

SuiteOneCaseTwo.java -> SuiteOneCaseTwo Sheet

com.stta.SuiteTwo -> SuiteTwo.xls

SuiteTwoCaseOne.java -> SuiteTwoCaseOne Sheet

SuiteTwoCaseTwo.java -> SuiteTwoCaseTwo Sheet

八耳峦、編寫測試代碼

我們先嘗試從SuiteOne.xls文件的SuiteOneCaseOne sheet里讀取數(shù)據(jù),并驅(qū)動(dòng)測試用例SuiteOneCaseOne.java執(zhí)行焕毫。首先先寫SuiteBase.java蹲坷。

SuiteBase.java

SuiteBase類中創(chuàng)建一個(gè)初始化方法,用來初始化.xls文件路徑

package com.stta.TestSuiteBase;

import java.io.IOException;

import com.stta.utility.Read_XLS;

public class SuiteBase {

public static Read_XLS TestSuiteListExcel=null;

public static Read_XLS TestCaseListExcelOne=null;

public static Read_XLS TestCaseListExcelTwo=null;

public void init() throws IOException{

//代碼中文件路徑根據(jù)實(shí)際情況填寫

//使用Read_XLS工具類初始化測試測試套件列表TestSuiteList.xls

TestSuiteListExcel = new Read_XLS(System.getProperty("user.dir")+"\src\com\stta\ExcelFiles\TestSuiteList.xls");

//使用Read_XLS工具類初始化測試套件一SuiteOne.xls

TestCaseListExcelOne = new Read_XLS(System.getProperty("user.dir")+"\src\com\stta\ExcelFiles\SuiteOne.xls");

//使用Read_XLS工具類初始化測試套件二SuiteTwo.xls

TestCaseListExcelTwo = new Read_XLS(System.getProperty("user.dir")+"\src\com\stta\ExcelFiles\SuiteTwo.xls");

}

}

SuiteOneBase.java

SuiteOneBase類在這個(gè)步驟中我們還不實(shí)現(xiàn)任何功能邑飒,僅僅繼承了SuiteBase類

package com.stta.SuiteOne;

import com.stta.TestSuiteBase.SuiteBase;

//SuiteOneBase 類繼承? SuiteBase 類.

public class SuiteOneBase extends SuiteBase{? ?

}

SuiteOneCaseOne.java

這是我們的測試類循签,在這個(gè)文件中我們從.xls文件讀取數(shù)據(jù)并打印出來。這個(gè)類 包含了下列三個(gè)方法:

1.checkCaseToRun()---使用testNG的@BeforeTest標(biāo)簽幸乒,它將在所有@Test方法之前被運(yùn)行懦底,這個(gè)方法只要就是調(diào)用SuiteBase類的Init() 來初始化.xls文件路徑,保存在變量FilePath中罕扎。

2.SuiteOneCaseOneTest():這個(gè)是測試方法,附帶@Test標(biāo)簽丐重,并使用dataProvider 來獲取數(shù)據(jù)

3.SuiteOneCaseOneData():從.xls文件讀取數(shù)據(jù)并返回給SuiteOneCaseOneTest()方法

package com.stta.SuiteOne;

import java.io.IOException;

import org.testng.annotations.BeforeTest;

import org.testng.annotations.DataProvider;

import org.testng.annotations.Test;

import com.stta.utility.Read_XLS;

import com.stta.utility.SuiteUtility;

//SuiteOneCaseOne 類 繼承自? SuiteOneBase 類.

public class SuiteOneCaseOne extends SuiteOneBase{

Read_XLS FilePath = null;?

String TestCaseName = null;

@BeforeTest

public void checkCaseToRun() throws IOException{

? ? //調(diào)用SuiteBase類的init()來初始化.xls文件

? ? init();

? ? FilePath = TestCaseListExcelOne;

? ? System.out.println("FilePath Is : "+FilePath);

? ? TestCaseName = this.getClass().getSimpleName();

? ? System.out.println("TestCaseName Is : "+TestCaseName);

}

//在每個(gè)迭代中接收4列的數(shù)據(jù).

@Test(dataProvider="SuiteOneCaseOneData")

public void SuiteOneCaseOneTest(String DataCol1,String DataCol2,String DataCol3,String ExpectedResult){

? ? System.out.println("Value Of DataCol1 = "+DataCol1);

? ? System.out.println("Value Of DataCol2 = "+DataCol2);

? ? System.out.println("Value Of DataCol3 = "+DataCol3);

? ? System.out.println("Value Of ExpectedResult = "+ExpectedResult);? ? ? ?

}?

//data provider回在每個(gè)迭代中一個(gè)一個(gè)返回4列數(shù)據(jù)

@DataProvider

public Object[][] SuiteOneCaseOneData(){

? ? //To retrieve data from Data 1 Column,Data 2 Column,Data 3 Column and Expected Result column of SuiteOneCaseOne data Sheet.

? ? //Last two columns (DataToRun and Pass/Fail/Skip) are Ignored programatically when reading test data.

? ? return SuiteUtility.GetTestDataUtility(FilePath, TestCaseName);

? ? }

}

九腔召、運(yùn)行數(shù)據(jù)讀取測試

到此為止,我們簡單的數(shù)據(jù)讀取測試已經(jīng)準(zhǔn)備完畢扮惦,可以試運(yùn)行一下確保沒問題臀蛛,再繼續(xù)往下。在SuiteOneCaseOne.java文件點(diǎn)擊右鍵選擇 Run As -> TestNG 。如果你是按照前述的步驟一步一步來的話浊仆,測試運(yùn)行時(shí)沒問題的客峭。因?yàn)镾uiteOneCaseOne數(shù)據(jù)sheet里有兩行數(shù)據(jù),所以@Test將會(huì)被執(zhí)行兩次抡柿。執(zhí)行完舔琅,就可以在控制臺(tái)看到如下信息:

如果你看到上述消息,說明到目前為止我們搭建的基于數(shù)據(jù)驅(qū)動(dòng)的自動(dòng)化是框架暫時(shí)是沒有問題的洲劣,已經(jīng)可以成功簡單的數(shù)據(jù)讀入測試备蚓。

創(chuàng)建了一個(gè)測試交流群,如果對(duì)軟件測試囱稽、接口測試郊尝、自動(dòng)化測試、面試經(jīng)驗(yàn)交流感興趣可以加測試交流群:829792258战惊,還會(huì)有同行一起技術(shù)交流

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末流昏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子吞获,更是在濱河造成了極大的恐慌况凉,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衫哥,死亡現(xiàn)場離奇詭異茎刚,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)撤逢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門膛锭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蚊荣,你說我怎么就攤上這事初狰。” “怎么了互例?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵奢入,是天一觀的道長。 經(jīng)常有香客問我媳叨,道長腥光,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任糊秆,我火速辦了婚禮武福,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘痘番。我一直安慰自己捉片,他們只是感情好平痰,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伍纫,像睡著了一般宗雇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上莹规,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天赔蒲,我揣著相機(jī)與錄音,去河邊找鬼访惜。 笑死嘹履,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的债热。 我是一名探鬼主播砾嫉,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼窒篱!你這毒婦竟也來了焕刮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤墙杯,失蹤者是張志新(化名)和其女友劉穎配并,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體高镐,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡溉旋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嫉髓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片观腊。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖算行,靈堂內(nèi)的尸體忽然破棺而出梧油,到底是詐尸還是另有隱情,我是刑警寧澤州邢,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布儡陨,位于F島的核電站,受9級(jí)特大地震影響量淌,放射性物質(zhì)發(fā)生泄漏骗村。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一呀枢、第九天 我趴在偏房一處隱蔽的房頂上張望叙身。 院中可真熱鬧,春花似錦硫狞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽财忽。三九已至,卻和暖如春泣侮,著一層夾襖步出監(jiān)牢的瞬間即彪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國打工活尊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留隶校,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓蛹锰,卻偏偏與公主長得像深胳,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子铜犬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348