一、原理及特點
1. 關鍵字驅動測試是數據驅動測試的一種改進類型
2. 主要關鍵字包括三類:被操作對象(Item)、操作(Operation)和值(value),用面向對象形式可將其表現為Item.Operation(Value)
3. 將測試邏輯按照這些關鍵字進行分解,形成數據文件。
4. 用關鍵字的形式將測試邏輯封裝在數據文件中,測試工具只要能夠解釋這些關鍵字即可對其應用自動化
二、准備
使用工具:eclipse
用到的第三方jar包:poi.jar(操作excel);selenium.jar
理解難點:java反射機制;逐步分層
三、框架構思
1、編寫腳本
首先我們來寫一個登陸開源中國的腳本
1 public class Login_Script { 2 public static WebDriver driver=null; 3 public static void main(String []agrs) throws InterruptedException{ 4 // 啟動火狐瀏覽器 5 driver= new FirefoxDriver(); 6 // 最大化 7 driver.manage().window().maximize(); 8 // 打開開源中國網址 9 driver.get("http://www.oschina.net/"); 10 // 點擊登錄 11 driver.findElement(By.xpath("//*[@id='OSC_Userbar']/a[1]")).click(); 12 // 輸入用戶名 13 driver.findElement(By.xpath("//*[@id='f_email']")).sendKeys("XXXXXXB"); 14 // 輸入密碼 15 driver.findElement(By.xpath("//*[@id='f_pwd']")).sendKeys("XXXXXXXA"); 16 // 點擊登錄按鈕 17 // driver.findElement(By.xpath("//*[@id='login_osc']/table/tbody/tr[7]/td/input")).click(); 18 // Thread.sleep(30); 19 // 點擊退出按鈕 20 driver.findElement(By.xpath("//*[@id='OSC_Userbar']/a[3]")).click(); 21 // 關閉瀏覽器 22 driver.quit(); 23 } 24 }
2、腳本分析
這是登陸的場景
操作步驟
第一步:啟動瀏覽器
第二步:輸入網址
第四步:點擊登錄
第五步:輸入用戶名
第六步:輸入密碼
第七步:點擊登錄按鈕
第八步:點擊退出
第九步:關閉瀏覽器
3、使用excel
建立一個excel

在java中創建一個操作excel的類 ,主要實現是對excel的讀和寫,主要代碼如下:
1 public class ExcelUtils { 2 public static HSSFSheet ExcelSheet; 3 public static HSSFWorkbook ExcelBook; 4 public static HSSFRow Row; 5 public static HSSFCell Cell; 6 public static void setExcelFile(String Path,String SheetName) throws Exception{ 7 FileInputStream ExcelFile=new FileInputStream(Path); 8 ExcelBook=new HSSFWorkbook(ExcelFile); 9 ExcelSheet=ExcelBook.getSheet(SheetName); 10 } 11 public static void setCellData(String Result, int RowNum, int ColNum,String Path) throws Exception{ 12 Row = ExcelSheet.getRow(RowNum); 13 Cell = Row.getCell(ColNum, Row.RETURN_BLANK_AS_NULL); 14 if (Cell == null) { 15 Cell = Row.createCell(ColNum); 16 Cell.setCellValue(Result); 17 } else { 18 Cell.setCellValue(Result); 19 } 20 FileOutputStream fileOut = new FileOutputStream(Path); 21 ExcelBook.write(fileOut); 22 fileOut.flush(); 23 fileOut.close(); 24 } 25 public static String getCellDate(int RowNum,int CloNum){ 26 Cell=ExcelSheet.getRow(RowNum).getCell(CloNum); 27 String cellData=Cell.getStringCellValue(); 28 return cellData; 29 } 30 }
4、新建一個ActionKeyWords類
1 public class ActionKeyWords { 2 public static WebDriver driver=null; 3 // 啟動瀏覽器並最大化 4 public static void OpenBrowser (){ 5 driver= new FirefoxDriver(); 6 driver.manage().window().maximize(); 7 } 8 // 打開開源中國網址 9 public static void Navigate (){ 10 driver.get("http://www.oschina.net/"); 11 } 12 // 點擊登錄 13 public static void Login_Click (){ 14 driver.findElement(By.xpath("//*[@id='OSC_Userbar']/a[1]")).click(); 15 } 16 // 輸入用戶名 17 public static void Input_Name (){ 18 driver.findElement(By.xpath("//*[@id='f_email']")).sendKeys("XXXXXXA"); 19 } 20 // 輸入密碼 21 public static void Input_Password (){ 22 driver.findElement(By.xpath("//*[@id='f_pwd']")).sendKeys("XXXXXXB"); 23 } 24 // 點擊登錄按鈕 25 public static void Login_Button (){ 26 driver.findElement(By.xpath("//*[@id='login_osc']/table/tbody/tr[7]/td/input")).click(); 27 } 28 // 點擊退出按鈕 29 public static void Logout_Click (){ 30 driver.findElement(By.xpath("//*[@id='OSC_Userbar']/a[3]")).click(); 31 } 32 // 關閉瀏覽器 33 public static void CloseBrowser (){ 34 driver.quit(); 35 } 36 }
5、修改Login_Script腳本.
1 public class Login_Script { 2 public static void main(String []agrs) throws Exception{ 3 ExcelUtils.setExcelFile("D:\\data\\TestData.xls", "steps"); 4 ActionKeyWords actionKeyWords= new ActionKeyWords(); 5 String Keywords=null; 6 for(int RowNum=1;RowNum<=ExcelUtils.getLastRowNums();RowNum++){ 7 Keywords=ExcelUtils.getCellDate(RowNum, 3); 8 if(Keywords.trim().equals("OpenBrowser")){ 9 actionKeyWords.OpenBrowser(); 10 }else if(Keywords.trim().equals("Navigate")){ 11 actionKeyWords.Navigate(); 12 }else if(Keywords.trim().equals("Login_Click")){ 13 actionKeyWords.Login_Click(); 14 }else if(Keywords.trim().equals("Input_Name")){ 15 actionKeyWords.Input_Name(); 16 }else if(Keywords.trim().equals("Input_Password")){ 17 actionKeyWords.Input_Password(); 18 }else if(Keywords.trim().equals("Login_Button")){ 19 actionKeyWords.Login_Button(); 20 }else if(Keywords.trim().equals("Logout_Click")){ 21 actionKeyWords.Logout_Click(); 22 }else if(Keywords.trim().equals("CloseBrowser")){ 23 actionKeyWords.CloseBrowser(); 24 } 25 } 26 } 27 }
這樣代碼的框架就基本已經搭建起來了,代碼結構如下:

四、結構優化
1、優化Login_Script 類中的代碼
注:這里用到了反射機制
1 public class Login_Script { 2 public static ActionKeyWords actionKeyWords; 3 public static String Keywords=null; 4 public static Method[] method; 5 public Login_Script(){ 6 actionKeyWords= new ActionKeyWords(); 7 method=actionKeyWords.getClass().getMethods(); 8 } 9 public static void main(String []agrs) throws Exception{ 10 ExcelUtils.setExcelFile("D:\\data\\TestData.xls", "steps"); 11 new Login_Script(); 12 for(int RowNum=1;RowNum<=ExcelUtils.getLastRowNums();RowNum++){ 13 Keywords=ExcelUtils.getCellDate(RowNum, 3); 14 login_action(); 15 } 16 } 17 public static void login_action(){ 18 for(int i=0;i<method.length;i++){ 19 // System.out.println(method[i].getName()+" "+actionKeyWords+Keywords); 20 if(method[i].getName().trim().equals(Keywords)){ 21 try { 22 method[i].invoke(actionKeyWords); 23 } catch (IllegalAccessException e) { 24 // TODO Auto-generated catch block 25 e.printStackTrace(); 26 } catch (IllegalArgumentException e) { 27 // TODO Auto-generated catch block 28 e.printStackTrace(); 29 } catch (InvocationTargetException e) { 30 // TODO Auto-generated catch block 31 e.printStackTrace(); 32 } 33 } 34 } 35 } 36 }
2、將程序中的常量統一管理
例如:網頁的地址,賬戶、密碼,excel路徑,這里我們在文件下面建立一個
public class Contants { public static String url="http://www.oschina.net/"; public static String excelFile="D:\\data\\"; public static String excelName="TestData.xls"; public static String excelSheet="steps"; public static int excelKWCloNum=3; public static String userName="XXXXXXXA"; public static String userPassword="XXXXXB"; }
3、增加對象庫
下面我們看一下ActionKeyWords類中定位元素的路徑 是在代碼里面的,如果每次去修改的定位路徑的是時候都要修改代碼,為了便於維護,我們將這些元素的對象放在一個文件中,同時我們在Excel增加一列 Page Objects,這樣程序根據Excel中的Page Objects,去文件中讀取相應的元素,這里我們增加一個類OrpUtil,讀取元素的對象
1 # Home Page Objects 2 Userbar_login=//*[@id='OSC_Userbar']/a[1] 3 Userbar_logout=//div[@id='OSC_Userbar']/a[3] 4 #Login Page Objects 5 Input_name=//*[@id='f_email'] 6 Input_password=//*[@id='f_pwd'] 7 Login_button=//*[@id='login_osc']/table/tbody/tr[7]/td/input 8 //OrpUtil類 9 public class OrpUtil { 10 public static String readValue(String a){ 11 Properties pro=new Properties(); 12 String popath=Contants.ObjectReUrl; 13 String value=null; 14 try { 15 InputStream in =new BufferedInputStream(new FileInputStream(popath)); 16 pro.load(in); 17 value=pro.getProperty(a); 18 } catch (FileNotFoundException e) { 19 // TODO Auto-generated catch block 20 e.printStackTrace(); 21 }catch (IOException e) { 22 // TODO Auto-generated catch block 23 e.printStackTrace(); 24 } 25 return value; 26 } 27 }
優化后的ActionKeyWords類
1 public class ActionKeyWords { 2 public static WebDriver driver=null; 3 // 啟動瀏覽器並最大化 4 public static void OpenBrowser (String OR){ 5 System.setProperty("webdriver.chrome.driver", ".//server//chromedriver.exe"); 6 driver= new ChromeDriver(); 7 driver.manage().window().maximize(); 8 } 9 // 打開開源中國網址 10 public static void Navigate (String OR){ 11 driver.get(Contants.url); 12 } 13 // 點擊登錄 14 public static void Login_Click (String OR){ 15 driver.findElement(By.xpath(OrpUtil.readValue(OR))).click(); 16 } 17 // 輸入用戶名 18 public static void Input_Name (String OR){ 19 driver.findElement(By.xpath(OrpUtil.readValue(OR))).clear(); 20 driver.findElement(By.xpath(OrpUtil.readValue(OR))).sendKeys(Contants.userName); 21 } 22 // 輸入密碼 23 public static void Input_Password (String OR){ 24 driver.findElement(By.xpath(OrpUtil.readValue(OR))).click(); 25 driver.findElement(By.xpath(OrpUtil.readValue(OR))).sendKeys(Contants.userPassword); 26 } 27 // 點擊登錄按鈕 28 public static void Login_Button (String OR){ 29 driver.findElement(By.xpath(OrpUtil.readValue(OR))).click(); 30 } 31 // 點擊退出按鈕 32 public static void Logout_Click (String OR){ 33 try { 34 Thread.sleep(300); 35 driver.findElement(By.xpath(OrpUtil.readValue(OR))).click(); 36 } catch (InterruptedException e) { 37 // TODO Auto-generated catch block 38 e.printStackTrace(); 39 } 40 } 41 // 關閉瀏覽器 42 public static void CloseBrowser (String OR){ 43 driver.quit(); 44 } 45 }
這個OR的值是從Excel中讀取的

4、增加測試場景
從Excel中我們可以看到,這操作是對應的用例編寫中的我們的操作步驟,在用例設計的時候還有測試場景和結果,這里
我們先增加個場景在EXCEL中增加一個名稱為Suite的Sheet頁

我們程序的運行邏輯是循環讀取Suite頁中的Runmode,當為YES時根據對應的TestSuiteID去讀取對應的Steps頁中的操作在步驟,進行運行
1 public static void main(String []agrs) throws Exception{ 2 ExcelUtils.setExcelFile(Contants.excelFile+Contants.excelName ); 3 new Login_Script(); 4 bResult = true; 5 // 循環讀取suitSheet里面的值,找出運行的場景 6 for(int j=1;j<=ExcelUtils.getLastRowNums(Contants.suitSheet);j++){ 7 8 String Runmode=ExcelUtils.getCellDate(j, Contants.suitRunmode,Contants.suitSheet); 9 String suitTestSuiteId=ExcelUtils.getCellDate(j, Contants.suitTestSuiteId,Contants.suitSheet); 10 int sRowNum; 11 12 if(Runmode.equals("YES")){ 13 // 根據stepTestSuiteId在caseSheet中循環查找相對應的執行步驟 14 for(sRowNum=1;sRowNum<=ExcelUtils.getLastRowNums(Contants.caseSheet);sRowNum++){ 15 String stepTestSuiteId=ExcelUtils.getCellDate(sRowNum, Contants.stepTestSuiteId,Contants.caseSheet); 16 System.out.println(ExcelUtils.getCellDate(sRowNum, Contants.excelKWCloNum,Contants.caseSheet)); 17 if(stepTestSuiteId.trim().equals(suitTestSuiteId)){ 18 Keywords=ExcelUtils.getCellDate(sRowNum, Contants.excelKWCloNum,Contants.caseSheet); 19 r=ExcelUtils.getCellDate(sRowNum, Contants.excelPOCloNum,Contants.caseSheet); 20 login_action(sRowNum); 21 if(bResult == false){ 22 ExcelUtils.setCellData(Contants.fail, j, Contants.suitResult,Contants.excelFile+Contants.excelName, Contants.suitSheet); 23 24 } 25 } 26 } 27 if(bResult == true){ 28 ExcelUtils.setCellData(Contants.pass, j, Contants.suitResult,Contants.excelFile+Contants.excelName, Contants.suitSheet); 29 } 30 31 }else{ 32 33 System.out.println("沒有要執行的用例"); 34 break; 35 } 36 37 } 38 39 40 } 41
5、增加測試結果
在Excel中新增一列Resut

在Login_Script中定義一個boolean類型的變量bResult,默認是true在各個地方try,,cacth,當出現異常的時候在bResult賦值為false,在Excel工具類中增加一個寫入excel值得方法
五、小結
這樣我們的關鍵字驅動框架就初步搭好了,下面我們回歸一下基本思路:
代碼地址:http://git.oschina.net/hellotester/SeleniumKeywordDrive
參考文獻:http://www.toolsqa.com/selenium-webdriver/keyword-driven-framework/introduction/
