【转】UI自动化测试框架之Selenium关键字驱动

原网址:https://my.oschina.net/hellotest/blog/531932#comment-list
摘要: 自动化测试框架demo,用关键字的形式将测试逻辑封装在数据文件中,测试工具解释这些关键字即可对其应用自动化

一、原理及特点

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/

原文地址:https://www.cnblogs.com/gcgc/p/6396348.html