文档章节

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

红焖鲤鱼
 红焖鲤鱼
发布于 2015/11/18 11:47
字数 1826
阅读 11705
收藏 150
点赞 18
评论 14

一、原理及特点

1.   关键字驱动测试是数据驱动测试的一种改进类型

2.    主要关键字包括三类:被操作对象(Item)、操作(Operation)和值(value),用面向对象形式可将其表现为Item.Operation(Value)

3.   将测试逻辑按照这些关键字进行分解,形成数据文件。

4.    用关键字的形式将测试逻辑封装在数据文件中,测试工具只要能够解释这些关键字即可对其应用自动化

二、准备

使用工具:eclipse

用到的第三方jar包:poi.jar(操作excel);selenium.jar

理解难点:java反射机制;逐步分层

三、框架构思

1、编写脚本

首先我们来写一个登陆开源中国的脚本

public class Login_Script {
            public static WebDriver driver=null;
            public static void main(String []agrs) throws InterruptedException{
//                启动火狐浏览器
                driver= new FirefoxDriver();
//                最大化
                driver.manage().window().maximize();
//                打开开源中国网址
                driver.get("http://www.oschina.net/");
//                点击登录
                driver.findElement(By.xpath("//*[@id='OSC_Userbar']/a[1]")).click();
//                输入用户名
                driver.findElement(By.xpath("//*[@id='f_email']")).sendKeys("XXXXXXB");
//                输入密码
                driver.findElement(By.xpath("//*[@id='f_pwd']")).sendKeys("XXXXXXXA");
//                点击登录按钮
//                driver.findElement(By.xpath("//*[@id='login_osc']/table/tbody/tr[7]/td/input")).click();
//                Thread.sleep(30);
//                点击退出按钮
                driver.findElement(By.xpath("//*[@id='OSC_Userbar']/a[3]")).click();
//                关闭浏览器
                driver.quit();
                }
}

2、脚本分析

这是登陆的场景

操作步骤

第一步:启动浏览器

第二步:输入网址

第四步:点击登录

第五步:输入用户名

第六步:输入密码

第七步:点击登录按钮

第八步:点击退出

第九步:关闭浏览器

3、使用excel

建立一个excel

在java中创建一个操作excel的类 ,主要实现是对excel的读和写,主要代码如下:

public class ExcelUtils {
        public static HSSFSheet ExcelSheet;
        public static HSSFWorkbook    ExcelBook;
        public static HSSFRow Row;
        public static HSSFCell    Cell;
        public static void setExcelFile(String Path,String    SheetName) throws Exception{
            FileInputStream    ExcelFile=new FileInputStream(Path);
            ExcelBook=new HSSFWorkbook(ExcelFile);
            ExcelSheet=ExcelBook.getSheet(SheetName);        
        }
        public static void setCellData(String Result,  int RowNum, int ColNum,String Path) throws Exception{
              Row  = ExcelSheet.getRow(RowNum);
            Cell = Row.getCell(ColNum, Row.RETURN_BLANK_AS_NULL);
            if (Cell == null) {
                Cell = Row.createCell(ColNum);
                Cell.setCellValue(Result);
                } else {
                    Cell.setCellValue(Result);
                }
            FileOutputStream fileOut = new FileOutputStream(Path);
            ExcelBook.write(fileOut);
            fileOut.flush();
            fileOut.close();
        }
        public static String getCellDate(int RowNum,int CloNum){
            Cell=ExcelSheet.getRow(RowNum).getCell(CloNum);
            String cellData=Cell.getStringCellValue();
            return cellData;
        }
}

4、新建一个ActionKeyWords类

public class ActionKeyWords {
    public static WebDriver driver=null;
//    启动浏览器并最大化
    public static void OpenBrowser (){
        driver= new FirefoxDriver();
        driver.manage().window().maximize();
    }
//    打开开源中国网址
    public static void Navigate (){
        driver.get("http://www.oschina.net/");
    }
//    点击登录
    public static void Login_Click (){
        driver.findElement(By.xpath("//*[@id='OSC_Userbar']/a[1]")).click();
    }
//    输入用户名
    public static void Input_Name (){
        driver.findElement(By.xpath("//*[@id='f_email']")).sendKeys("XXXXXXA");
    }
//    输入密码
    public static void Input_Password (){
        driver.findElement(By.xpath("//*[@id='f_pwd']")).sendKeys("XXXXXXB");
    }
//    点击登录按钮
    public static void Login_Button (){
        driver.findElement(By.xpath("//*[@id='login_osc']/table/tbody/tr[7]/td/input")).click();
    }
    //    点击退出按钮
    public static void Logout_Click (){
        driver.findElement(By.xpath("//*[@id='OSC_Userbar']/a[3]")).click();
    }
//    关闭浏览器
    public static void CloseBrowser (){
        driver.quit();
    }
}

5、修改Login_Script脚本.

public class Login_Script {
            public static void main(String []agrs) throws Exception{
                ExcelUtils.setExcelFile("D:\\data\\TestData.xls", "steps");
                ActionKeyWords actionKeyWords= new ActionKeyWords();
                String Keywords=null;
                for(int RowNum=1;RowNum<=ExcelUtils.getLastRowNums();RowNum++){
                    Keywords=ExcelUtils.getCellDate(RowNum, 3);
                    if(Keywords.trim().equals("OpenBrowser")){
                        actionKeyWords.OpenBrowser();
                    }else if(Keywords.trim().equals("Navigate")){
                        actionKeyWords.Navigate();
                    }else if(Keywords.trim().equals("Login_Click")){
                        actionKeyWords.Login_Click();
                    }else if(Keywords.trim().equals("Input_Name")){
                        actionKeyWords.Input_Name();
                    }else if(Keywords.trim().equals("Input_Password")){
                        actionKeyWords.Input_Password();
                    }else if(Keywords.trim().equals("Login_Button")){
                        actionKeyWords.Login_Button();
                    }else if(Keywords.trim().equals("Logout_Click")){
                        actionKeyWords.Logout_Click();
                    }else if(Keywords.trim().equals("CloseBrowser")){
                        actionKeyWords.CloseBrowser();
                    }
                }
            }
}

这样代码的框架就基本已经搭建起来了,代码结构如下:

四、结构优化

1、优化Login_Script 类中的代码

注:这里用到了反射机制

 public class Login_Script {
            public static ActionKeyWords actionKeyWords;
            public static String Keywords=null;
            public static Method[] method;
            public Login_Script(){
                actionKeyWords= new ActionKeyWords();
                method=actionKeyWords.getClass().getMethods();
            }
            public static void main(String []agrs) throws Exception{
                ExcelUtils.setExcelFile("D:\\data\\TestData.xls", "steps");
                new Login_Script();
                for(int RowNum=1;RowNum<=ExcelUtils.getLastRowNums();RowNum++){
                    Keywords=ExcelUtils.getCellDate(RowNum, 3);
                    login_action();
                }
            }
            public static void login_action(){
                for(int i=0;i<method.length;i++){
//                    System.out.println(method[i].getName()+"     "+actionKeyWords+Keywords);
                    if(method[i].getName().trim().equals(Keywords)){
                        try {
                            method[i].invoke(actionKeyWords);
                        } catch (IllegalAccessException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (IllegalArgumentException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
            }
}

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,读取元素的对象 

# Home Page Objects
Userbar_login=//*[@id='OSC_Userbar']/a[1]
Userbar_logout=//div[@id='OSC_Userbar']/a[3]
#Login Page Objects
Input_name=//*[@id='f_email']
Input_password=//*[@id='f_pwd']
Login_button=//*[@id='login_osc']/table/tbody/tr[7]/td/input
//OrpUtil类
public class OrpUtil {
    public static String  readValue(String a){
        Properties pro=new Properties();
        String popath=Contants.ObjectReUrl;
        String value=null;
        try {
            InputStream in =new BufferedInputStream(new FileInputStream(popath));
            pro.load(in);
            value=pro.getProperty(a);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return value;
    }
}

优化后的ActionKeyWords

public class ActionKeyWords {
    public static WebDriver driver=null;
//    启动浏览器并最大化
    public static void OpenBrowser (String OR){
        System.setProperty("webdriver.chrome.driver", ".//server//chromedriver.exe");
        driver= new ChromeDriver();
        driver.manage().window().maximize();
    }
//    打开开源中国网址
    public static void Navigate (String OR){
        driver.get(Contants.url);
    }
//    点击登录
    public static void Login_Click (String OR){
        driver.findElement(By.xpath(OrpUtil.readValue(OR))).click();
    }
//    输入用户名
    public static void Input_Name (String OR){
        driver.findElement(By.xpath(OrpUtil.readValue(OR))).clear();
        driver.findElement(By.xpath(OrpUtil.readValue(OR))).sendKeys(Contants.userName);
    }
//    输入密码
    public static void Input_Password (String OR){
        driver.findElement(By.xpath(OrpUtil.readValue(OR))).click();
        driver.findElement(By.xpath(OrpUtil.readValue(OR))).sendKeys(Contants.userPassword);
    }
//    点击登录按钮
    public static void Login_Button (String OR){
        driver.findElement(By.xpath(OrpUtil.readValue(OR))).click();
    }
    //    点击退出按钮
    public static void Logout_Click (String OR){
        try {
            Thread.sleep(300);
            driver.findElement(By.xpath(OrpUtil.readValue(OR))).click();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
//    关闭浏览器
    public static void CloseBrowser (String OR){
        driver.quit();
    }
}

这个OR的值是从Excel中读取的

 

 

4、增加测试场景

从Excel中我们可以看到,这操作是对应的用例编写中的我们的操作步骤,在用例设计的时候还有测试场景和结果,这里

我们先增加个场景在EXCEL中增加一个名称为Suite的Sheet页

我们程序的运行逻辑是循环读取Suite页中的Runmode,当为YES时根据对应的TestSuiteID去读取对应的Steps页中的操作在步骤,进行运行

public static void main(String []agrs) throws Exception{
				ExcelUtils.setExcelFile(Contants.excelFile+Contants.excelName );
				new Login_Script();
				bResult = true;
//				循环读取suitSheet里面的值,找出运行的场景
				for(int j=1;j<=ExcelUtils.getLastRowNums(Contants.suitSheet);j++){
					
					String Runmode=ExcelUtils.getCellDate(j, Contants.suitRunmode,Contants.suitSheet);
					String suitTestSuiteId=ExcelUtils.getCellDate(j, Contants.suitTestSuiteId,Contants.suitSheet);
					int sRowNum;
					
					if(Runmode.equals("YES")){
//						根据stepTestSuiteId在caseSheet中循环查找相对应的执行步骤
						for(sRowNum=1;sRowNum<=ExcelUtils.getLastRowNums(Contants.caseSheet);sRowNum++){
							String stepTestSuiteId=ExcelUtils.getCellDate(sRowNum, Contants.stepTestSuiteId,Contants.caseSheet);
							System.out.println(ExcelUtils.getCellDate(sRowNum, Contants.excelKWCloNum,Contants.caseSheet));
							if(stepTestSuiteId.trim().equals(suitTestSuiteId)){				
								Keywords=ExcelUtils.getCellDate(sRowNum, Contants.excelKWCloNum,Contants.caseSheet);
								r=ExcelUtils.getCellDate(sRowNum, Contants.excelPOCloNum,Contants.caseSheet);
								login_action(sRowNum);
								if(bResult == false){
									ExcelUtils.setCellData(Contants.fail, j, Contants.suitResult,Contants.excelFile+Contants.excelName, Contants.suitSheet);
									
								}
							}	
						}
						if(bResult == true){
							ExcelUtils.setCellData(Contants.pass, j, Contants.suitResult,Contants.excelFile+Contants.excelName, Contants.suitSheet);
						}
																								
					}else{
						
						System.out.println("没有要执行的用例");
						break;
					}
					
				}
				
								
			}

 

5、增加测试结果

在Excel中新增一列Resut

 

在Login_Script中定义一个boolean类型的变量bResult,默认是true在各个地方try,,cacth,当出现异常的时候在bResult赋值为false,在Excel工具类中增加一个写入excel值得方法

五、小结

这样我们的关键字驱动框架就初步搭好了,下面我们回归一下基本思路

        

代码地址:http://git.oschina.net/hellotester/SeleniumKeywordDrive

 

欢迎大家关注微信公众号进行交流

© 著作权归作者所有

共有 人打赏支持
红焖鲤鱼
粉丝 111
博文 36
码字总数 27195
作品 0
浦东
QA/测试工程师
加载中

评论(14)

北_木
北_木
赞~
f
free007
博主,牛逼!佩服,测试行业的顶尖高手!
7
757563246
Keywords=ExcelUtils.getCellDate(sRowNum, Contants.excelKWCloNum,Contants.caseSheet);
r=ExcelUtils.getCellDate(sRowNum, Contants.excelPOCloNum,Contants.caseSheet);
login_action(sRowNum);
Keywords ,r ,login_action 三个的方法是什么,能给完整的代码吗?
红焖鲤鱼
红焖鲤鱼

引用来自“chenhua0725”的评论

0 请问这个是什么错?是少jar包吗?
Buildfile: C:\Users\Administrator\workspace\selenium\SeleniumKeywordDrive\build.xml
[taskdef] Could not load definitions from resource testngtasks. It could not be found.
all:
[taskdef] Could not load definitions from resource testngtasks. It could not be found.
clean:
compile:

BUILD FAILED
C:\Users\Administrator\workspace\selenium\SeleniumKeywordDrive\build.xml:54: The following error occurred while executing this line:
C:\Users\Administrator\workspace\selenium\SeleniumKeywordDrive\build.xml:15: Directory C:\Users\lc\git\hello\bin creation was not successful for an unknown reason

Total time: 699 milliseconds
应该是的,也可能是你的build.xml配置的jar包路径的问题
chenhua0725
chenhua0725
0 请问这个是什么错?是少jar包吗?
Buildfile: C:\Users\Administrator\workspace\selenium\SeleniumKeywordDrive\build.xml
[taskdef] Could not load definitions from resource testngtasks. It could not be found.
all:
[taskdef] Could not load definitions from resource testngtasks. It could not be found.
clean:
compile:

BUILD FAILED
C:\Users\Administrator\workspace\selenium\SeleniumKeywordDrive\build.xml:54: The following error occurred while executing this line:
C:\Users\Administrator\workspace\selenium\SeleniumKeywordDrive\build.xml:15: Directory C:\Users\lc\git\hello\bin creation was not successful for an unknown reason

Total time: 699 milliseconds
红焖鲤鱼
红焖鲤鱼

引用来自“chenhua0725”的评论

楼主,下载你的代码导不进eclipse里,你是用哪个版本的eclipse?
可以在eclipse中建一个java项目,然后把文件复制进去直接覆盖,或者将项目复制到eclipse中右键-》configure-》convert to JPA project->>java
chenhua0725
chenhua0725
楼主,下载你的代码导不进eclipse里,你是用哪个版本的eclipse?
Robot-xiakun
Robot-xiakun
Tom-Lin
Tom-Lin
好用吗?
猪的暧昧
猪的暧昧
mark
学习自动化测试的一些感悟

这个话题比较大,相信大家也都有自己的想法,我在这里写一些我自己的看法,请大家指教。 1、什么叫做自动化测试工程师? 首先,要会使用自动化测试工具; 接下来,对于高手来说,要能写一些独...

白一客
2017/05/25
111
0
WebUi 自动化测试框架--PatatiumWebUi

这是一个webui自动化测试框架,由webdriver中文社区创办人土豆(本人技术笔名)所创建,该web自动化测试框架是用java语言编写的,基于selenium webdriver 的开源自动化测试框架,该框架结合了t...

郑树恒
2016/08/31
1K
0
webUI 自动化测试框架 PatatiumWebUi 发布

这是一个 webui 自动化测试框架,由 webdriver中文社区创办人土豆(本人技术笔名)所创建,该 web 自动化测试框架是用Java 语言编写的,基于 selenium webdriver 的开源自动化测试框架,该框架...

郑树恒
2016/08/31
3.6K
0
App 自动化测试框架--PatatiumAppUi

这是一个AppUi自动化测试框架,由webdriver中文社区创办人土豆(本人技术笔名)所创建。 该APP自动化测试框架是用Java语言编写的,基于selenium webdriver Appium的开源自动化测试框架,该框架...

郑树恒
2016/09/05
787
0
分分钟玩转UI自动化测试

有没有那么一刻,看到自动模拟用户操作界面感觉好神奇。 timg.jpg 关于什么叫UI自动化测试就不解释了,基本上是你刚才脑海里想到什么就是什么。 在分层自动化测试中包括:UI测试、集成/接口测...

BeckJin
2017/04/22
0
0
《RobotFrameWork剖析》序——关于RobotFrameWork一些想法

其实,写自动化,有很久一段时间了。用RobotFrameWork也有很久了,包括博客里面也发布了一百多篇关于自动化的文章,虽然都是发的私文没有公开,都是平时的一些问题处理。从到公司开始去使用这...

丰_申
2016/07/29
9
0
自动化测试技术解决方案

子曰“工欲善其事,必先利其器”,有一把顺手的“兵器”,能让我们的学习和工作达到事半功倍的效果 一、技术解决方案要求说明 不管选择什么技术解决方案,总得来说,应该要满足下面几个条件:...

阿阳啊啊
2017/11/18
0
0
带有机器人框架的.NET自动化测试

  Clayton Neal在软件测试和质量保证方面有超过13年的经验,其中有八年的Windows, web,和移动应用程序的测试自动化经验。他在测试领域的所有等级都工作过。最近他在Bloomberg and Misys...

糖糖豆豆
2014/10/16
0
1
docker+robot framework+selenium并发web应用UI自动化测试实践

自己在日常测试中,会搭建UI自动化测试框架来进行web应用的回归测试,在这过程中遇到了许多问题,如测试脚本和执行机不分离,串行测试效率低下,环境搭建麻烦等问题。在这个过程中,自己也在...

Ivanli1990
2017/09/03
0
0
基于selenium webdriver的一个web自动化测试框架PatatiumWebUi

PatatiumWebUi 简介 这是一个webui自动化测试框架,由webdriver中文社区创办人土豆(本人技术笔名)所创建,该web自动化测试框架是用java语言编写的,基于selenium webdriver 的开源自动化测试框...

郑树恒
2016/08/31
716
1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

打印斐波那契数

package com.jerry.ch04;public class PrintFibonacci {public static void main(String[] args) {for (int i=0; i<10; i++) {System.out.print(fib(i) + " ");}......

JerryNing
11分钟前
0
0
shell编程

一、shell脚本介绍

人在艹木中
11分钟前
0
0
istio 0.8 遥测 案例

==============遥测===================================== 演示如何从网格中收集遥测信息。 分布式跟踪。如何配置代理以向Zipkin或Jaeger发送跟踪请求 收集度量标准和日志。此任务说明如何配...

xiaomin0322
13分钟前
0
0
ND4J求多元线性回归以及GPU和CPU计算性能对比

上一篇博客《梯度下降法求多元线性回归及Java实现》简单了介绍了梯度下降法,并用Java实现了一个梯度下降法求回归的例子。本篇博客,尝试用dl4j的张量运算库nd4j来实现梯度下降法求多元线性回...

冷血狂魔
14分钟前
0
0
springboot常用注解

@SpringBootApplication: 包含@Configuration、@EnableAutoConfiguration、@ComponentScan 通常用在主类上。 @Service: 用于标注业务层组件。 @RestController: 用于标注控制层组件(如strut...

GoldenVein
20分钟前
1
0
如何进行大数据的入门级学习?

不知道你是计算机专业应届生还是已经从业者。总之,有java基础的学生学习大数据会轻松很多,零基础的小白都需要从java和linux学起。 如果你是一个学习能力特别强,而且自律性也很强的人的话可...

董黎明
34分钟前
0
0
使用Parcelable传递复杂参数

最近做AIDL传递对象,对象必须实现Parcelable的方法才可以被传递。 @Override    public int describeContents() {//这个 默认返回0就行了。        return 0;    }    ...

火云
35分钟前
0
0
十大Intellij IDEA快捷键

Intellij IDEA中有很多快捷键让人爱不释手,stackoverflow上也有一些有趣的讨论。每个人都有自己的最爱,想排出个理想的榜单还真是困难。以前也整理过Intellij的快捷键,这次就按照我日常开发...

HJCui
45分钟前
0
0
word 使用mathtype 编写 数学公式

下载安装,这个链接命名。。。。 http://www.mathtype.cn/xiazai.html 安装之后会多出一个选项 使用内联方式插入图表 编写公式的界面 设置支持latex 语法 输入公式回车就可以看到结果...

阿豪boy
今天
0
0
Promise

定义 Promise是异步编程的一种解决方案,所谓Promise就是一个容器,里面保存着某个未来才会结束的事件(通常是一个一步操作)的结果。 特点: 2.1 对象的状态不受外界影响,三种状态pending...

litCabbage
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部