java二次开发浏览器内核_深入理解基于Selenium的二次开发

对于做web端自动化测试的人来说,可能接触selenium比QTP还要多,但是我们在做基于selenium的二次开发的时候,经常会说到二次开发是 为了易于维护,很多人可能不懂得维护的价值是什么,和到底要维护什么。今天专门写一篇关于二次开发的文章,希望能够帮到有需要做二次开发的人。

二次开发也就是我们常说的封装selenium,或者做框架。但是一个框架要包含丰富的类和方法。要有一套完整的体系来帮助我们进行封装。可以说框架的设 计思想就是整个框架的灵魂,如果设计思想很正确也就意味着这个框架成功了一半,剩下的就是我们怎么样用程序实现这个思想,在开发的过程中我们也许会用到一 些设计模式和引用一些开源框架。这些只是一个开发人员或者程序设计者的基本素质。至于如果把selenium能够有效的封装和一些基本思想,我们来详细的 了解一下。

在这篇文章里面只针对selenium的webdriver来进行讨论,我们不再对rc做任何的解释和说明。我们都知道webdriver的使用过程中, 贯穿始终的就是一个driver, 并且这个driver代表了一个浏览器的当前窗口,我们进行操作的过程中只是进行当前窗口的操作,也就是最这个current window进行的一系列的操作,如果我们需要对打开的新的window来进行操作的话,我们需要switchTo,包括操作frame,当然整个流程下 的操作确实让我们觉得不是很难编写,但是我们编写脚本的过程中需要用到的一些辅助功能可能就会很难的编写,比如最大化浏览器,视角移动到操作的元素等等, 这个过程一次编写我们可以做到,但是反复的编写的话肯定是一个让人很头疼的过程,所以这个时候我们要去封装一些常用的方法,我们有了做一个比较完整的框架 的想法,但是我们忽然又意识到了,这样的话,我们需要把driver封装起来,因为整个测试的case都是针对的这个driver,并且只有一个 driver,这样子的话我们不允许创造多个的driver,也就意味着我们要把自己编写的小工具类和driver联系起来,并且我们的测试用例case 类也需要调用这个driver,其实很简单,我们可以用注入的方式来做,把driver当成tools类的一个属性值,然后注入到我们的case类中,也 可以通过set的方法来进行操作。有了这些基础,我们可以防止无限的编写重复的方法,这样我们有了自己的工具类。如果说这就是框架的话,就会显得非常的肤 浅,因为我们写的这些方法根本没有任何逻辑可言,只是把需要的方法统统的堆到了一起,所以这个时候我们需要想想用到某些方法来进行分一下层次。

Page类和Window类:

PageObject模式我们都知道,就是把资源都放入到page类里面,然后再编写逻辑类。这样的话就可以无限的复用这些资源,这只是笼统的讲了一下设 计的思想,至于PageObject到底怎么去实现这些设计呢?我们从webDriver的使用开始入手。webdriver是先从定义浏览器开始的。 WebDriver driver = new FirefoxDriver(); 这样我们就定义了一个firefox的浏览器,但是自动化的过程不可能只允许我们把定义浏览器的操作放在框架代码里面,那样的硬编码方式使我们的case 不存在可移植性了,如果进行兼容性测试的话,维护起来对这些case的修改量是比较大的,这种硬编码方式是我们不能够进行大量维护的,所以我们需要把定义 浏览器的过程完全放在case类里面,就是在我们写测试用例的时候再去编写到底用什么浏览器,防止在编写框架的时候硬编码的形式把浏览器写死在了框架里 面。做到多浏览器的可维护性,对于我们进行兼容测试也有一定的帮助,这样的话我们需要对浏览器的选择部分要进行一定的编码设计,来完成浏览器的可选择性。 在我们定义完了浏览器之后,这个时候我们也许觉得就是开始查找元素了,但是在这个driver的基础上我们应该发现其实这个时候driver代表的整个页 面的操作。但是在页面的操作基础上我们应该意识到还有一个级别的操作,那就是window的操作,就是针对浏览器自身的操作。包括一些基本的返回,向前, 最大化,最小化,或者移动到制定元素的位置,调用js等等等,这些方法的级别是出于window级别的,和页面无关的。所以我们应该把这些所有的方法都封 装到单独的一个层次中,我们暂且称之为window包中,刚才的浏览器的选择的所有方法我们放browser包中。这样我们设计出了两个层次。下面的设计 该如何进行呢?我们知道pageObject的思想是把资源都放入到我们定义的page类里面,所以这个时候我们需要思考了,我们如何设计这里的page 类呢?按照pageObject的思想来看,page类应该是我们自己编写的,那样我们的框架是不是就可以放弃编写page类了呢?直接封装一些通用的方 法?显然是不对的,对于页面html源码操作的过程中,我们烦透了这些元素查找的硬编码方式,在一个case里面或者两个case里面反复的调用编写是让 人头疼的一件事情,所以我们可以把所有的单页面看做一个层次,里面和PageObject的思想一样,就是放入了通用的方法,但是它存在的意义不只是这样 简单,因为我们操作的过程中需要涉及到frame。并且页面和页面之间涉及到不同window之间的切换,所以如何协调window和page之间的关系 成为了我们需要注意的难点和重点,我们知道webdriver里面有一个方法叫做getWindowHandlers,这个方法可以获得所有的句柄,我们 想设计这个page类那么意味着我们需要去完美的配合window类,他们之间唯一的关联就是这个方法,所以我们可以设计一个概念,叫做页面集合,在创建 window对象的时候我们就会自动的出现一个页面集合器,它的功能就是管理所有的在操作过程中打开的页面。并且能够指定一个特殊的page,就是当前页 面。也就是webdriver中的driver对象,因为它一直都是针对当前页面编程的。那样我们的window类里面就存在了两个属性,一个收集器,一 个当前页。这样我们在window的级别上就能够完全操作page类了,这样我们在case类设计的时候,只需要通过window类的级别进行编码就可以 了,完全可以把page类当作一种资源来处理,我们所有需要的东西都是通过page来获取的。page类的设计中我们一定要编写通用的方法。比如获取 title等等等,最主要的一点就是要进行frame的处理操作,我们如何把frame完美的结合在page里面呢?我们在普通的webdriver脚本 编写过程中可能反反复复的switchTo的方法让我们很恼火,并且很难让我们理解这些脚本到底是想表达什么意思呢?所以我们需要进行对page进行层次 上的小分级,就是把page类再分为一个frame的类和一个模块的类,因为一个大型页面里面,通用的结构和模块是很多的。我们单独的定义一个模块类,可 以让这些相同的结构复用在里面的方法。定义frame类主要是处理把定位到frame的操作从case类中脱离出来,我们编写到page类里面或者 frame类里面,提供一种方式或者方法来进行frame的定位就可以了,简单实用,并且简化case类的编写,毕竟case类并不是由设计者来编写,尽 量做到最简化。当然我们可以成这整个层次都是page类,放在page包里面。

Element类:

Element类就是我们常用的driver.findElement()的那种形式,就是元素类,什么是元素类呢?元素就是我们需要定位的那些东西,我 们在操作过程中很难知道一个findElement到底查找的是什么,因为所有的标签形式都是通过id或者各种各样的定位方式来实现的。这个时候我们需要 把各种各样的findElement都统统的放在一起,造成的脚本难以理解让后续接手的脚本开发人员可能头疼不已,所以我们可以做一些简单的加工。当然我 们还要做的一个最大的工作就是元素查找的封装。Element和Page类如何关联起来。我们知道page和webElement的关联就是一个 driver.findElement的方法。这样就可以在页面上查找元素了。所以我们也在element类中通过这种形式来进行他们之间的关联。我们通 过在element类中添加定位方式的形式来进行元素定位和page的关联,我们只需要在编写自己的page类的过程中直接加入element类就可以 了,element类提供了所有的关于element的方法,比如鼠标事件和键盘事件,还有更重要的元素定位方法。定位的方法在这里不做任何的推荐,因为 每个人的思路不同,实现的方式也不同,我个人比较偏向的做法是做一个xml来进行资源的管理,把所有需要的资源都放入到xml里面,这样我们就可以进行元 素的定位了。并且在后期维护中主要维护xml就可以进行对整个脚本进行维护了,不需要我们大量的重新进行源码的分析和修改了。当然这是设计的优化过程,因 为定位的实现我们还是需要自己来完成的,我们知道元素的定位方式各种各样,我们怎么来进行管理和定位呢?我们可以通过map的方法作为属性值来进行元素的 管理,他的各种定位方法存放在map中,我们需要的时候只需要调一下就可以了。通过观察源码findElement也是通过map的形式来进行元素定位存 储的。我们可以借鉴一下源码的实现方式。当然我们完全封装findElement也是可以的。说到这里可能我们有一个问题比较难以解决,那就是层级定位。 如果我们只是给element类添加定位方式的话,那么findElement提供的一级一级的定位方式我们就无法应用了,所以在element类中我们 必要还要提供findElement的方法进行层级定位。这只是为了把webdriver的所有方法都尽量应用到而已。其实通过xpath的方式我们就可 以基本上定位大多数的元素。剩下的内容就是我们对element内容的扩充了。我们可以把元素的更加具体的抽象出来,比如我们把 select,table,checkbox等等等的各种html标签元素显式的定义出来,在我们定义一个元素的时候我们能够更加清晰的看到这个元素的含 义,我们知道它是一个按钮或者table等等等,这些小元素的操作需要我们自己深入理解和开发,这里不做过多的介绍。

其他类:

通过这些层次的分析我们已经出现一个框架的雏形了,然后我们剩下的设计就是基于完善和优化了。在一个自动化过程中case类是非常重要的,我们需要知道 case类运行结束的结果报告和分析,所以case类的运行等等一系列的东西我们都得有统计,这些东西必须要我们提供一些类来实现,不过所幸的是,强大的 junit或者testng完全可以取代我们要去做的工作,他们可以很完美的提供这些功能,我们只需要介入这些开源包就可以了。我们使用QTP的过程中我 们经常会用到参数化,我们自动化的设计都有了,但是没有参数化的功能怎么办?我们应该先想象一下数据提供的方式。testng提供了一种参数化的形式,但 是它是需要在xml里面配置或者硬编码的形式来进行编写。不过它提供了一种dataprovider的方式来进行参数化,它传递参数的形式是 Object[][],我们可能希望使用参数的时候通过excel表格来完成,这些都是可以实现的,poi包提供了解析excel的功能,非常的强大。我 们可以自己编写解析类来进行参数化的功能编写,具体实现不再过多去说。调用的方式就简单多了,硬性的记住几个注解就可以了。case类的各种运行我们都有 了,还需要一些什么扩展呢?很显然就是日志的扩展。日志的设计也是很有技巧的。我们需要用日志监控某一些方法的话,如果前期没有直接加入日志功能,我们可 以通过spring的方式来进行日志切入操作。但是我们在观察日志的时候我们通常会希望知道到底运行到哪一步了,我们可以想一想,所有的操作都是基于 element或者window的,page的只是一个抽象出来的概念,所以我们只需要把日志加入到每一个element的方法和window的主要方法 里面就可以监控到整个运行的过程,毕竟我们不能够去亲自盯着屏幕一直。这样没个方法不外乎就是运行成功和失败,所以我们可以通过这种方式来进行编码。日志 的实现我们可以通过通过的log4j或者自己编写一个小的日志系统。都是可行的方案。

扩展类:

也许我们需要这些系统能够有良好的可移植性,我们可以自己编写类加载器,为以后做整个自动化的测试平台做准备。最主要都是我们做的这些操作可能需要越来简 单,所以我们可能会因为引入注解的方式来提供编码效率,所以我们还需要为注解类做一些辅助的工作。当然这些注解的开发需要我们做足足够的需求研究,并不是 无谓的去开发各种注解。这些注解的应用应该说很广泛,不再多说注解的好处。并且注解还有一点可应用的地方就是放在数据库的操作中,在自动化测试中,其实数 据库的测试也是一个大的难点。在这里我们只讨论前端自动化的设计,不过多的讨论别的东西。

前面讲到的这些类的存在形式其实就是在框架里面的一种层次,我们谈论的这些都是基于webdriver的,并且主要基于前端自动化测试的,当然自动化测试 不只包括这些,还包括服务器端,接口自动化,单元自动化等等。我个人的能力水平也是很有限,可能很多地方说到的不是很到位,希望能够通过这篇文章能够给那些希望学习自动化,希望编写小测试框架的童鞋,一点点的启发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/398064.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UVA 10600 ACM Contest and Blackout (次小生成树)

题目大意&#xff1a; 给n个节点&#xff0c;m条边&#xff0c;问最小生成树&#xff0c;次小生成树&#xff1f; ps&#xff1a;以前做次小生成树的时候估计没有掌握牢固&#xff0c;这次wa的好辛苦哟。 1 #include <cmath>2 #include <queue>3 #include <stri…

codeforces 234E Champions' League

传送门&#xff1a;http://codeforces.com/problemset/problem/234/E 题目大意&#xff1a;&#xff08;注意要用文件&#xff09;有n个队伍&#xff0c;每个队伍都有一个积分&#xff0c;按照积分高低顺序列出4个等级&#xff08;每个等级n/4个&#xff0c;所以n一定是4的倍数…

前端技术之_CSS详解第五天

前端技术之_CSS详解第五天 一、行高和字号 1.1 行高 CSS中&#xff0c;所有的行&#xff0c;都有行高。盒模型的padding&#xff0c;绝对不是直接作用在文字上的&#xff0c;而是作用在“行”上的。 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&qu…

pxe装机dhcp获取不到_关于PXE服务器环境搭建流程中遇到的问题及解决方法

环境准备中遇到的问题首先需要将系统镜像挂载到 /mnt&#xff1a;#mount /dev/sdd2 /mnt/usb_disk 将U盘挂载#cp rhel-server-7.6-x86_64-dvd.iso /home 系统镜像拷到本地#mount -o loop rhel-server-7.6-x86_64-dvd.iso /mnt问题&#xff1a;ifconfig命令未找到解决&#xff1…

DB天气app冲刺二阶段第七天

又冲刺了一个礼拜了 今天收获应该算是不小了 虽然进度上来说还是一点也没前进 但是找到了好几个突破口 明天继续 今天先不多说了困了。。转载于:https://www.cnblogs.com/gaih/p/4550612.html

一小时包教会 —— webpack 入门指南

什么是 webpack&#xff1f; webpack是近期最火的一款模块加载器兼打包工具&#xff0c;它能把各种资源&#xff0c;例如JS&#xff08;含JSX&#xff09;、coffee、样式&#xff08;含less/sass&#xff09;、图片等都作为模块来使用和处理。 我们可以直接使用 require(XXX) 的…

判断一个js对象,是否具有某个属性

一个对象&#xff0c;想必我们关注的最多的应该是它上面的属性有哪些吧。那么&#xff0c;怎么判断一个对象是否具有某个属性呢&#xff1f; 1 /*下面是一个对比&#xff0c;看看在判断是否包括一个键上面&#xff0c;Object结构和Set结构的写法不同。*/2 // 对象的写法3 …

JAVA如何代码静态检查术语_Sonar代码静态检查规则-JAVA篇(二)

最近又搜罗整理了一些代码扫描规则&#xff0c;今天继续把这些扫描规则分享给老铁们&#xff0c;以后想学一些开发规则了&#xff0c;直接打开学一学就好了。不多说&#xff0c;直接上干货&#xff01;规则五、".equals()" should not be used to test the values of…

【每日scrum】NO.5

进入冲刺第五天&#xff0c;软件的界面设计成为主打&#xff0c;收集学校的很多美图是我们组的任务&#xff1b; 问题在于软件已很难有很大的改进&#xff0c;大方向也都是变不了的转载于:https://www.cnblogs.com/wantong/p/4553003.html

Python Dataframe转List

1 from pandas import read_csv2 3 dataframe read_csv(rurl, nrows 86400, usecols [0,], enginepython)4 #nrows:读取行数&#xff0c;usecols[n,]:仅读取第n列&#xff0c;usecols[a,b,c]:读取a、b、c列5 dataset dataframe.values6 7 List []8 for k in dataset: 9 …

使用/proc/meminfo文件查看内存状态信息

在Linux下可以使用/proc/meminfo文件查看操作系统内存的使用状态# cat /proc/meminfo MemTotal: 16333852 kB MemFree: 1633564 kB Buffers: 212448 kB Cached: 4422808 kB SwapCached: 0 kB Active: 10343096 kB Inactiv…

java 简单图片浏览器_Java实现简单的图片浏览器

第一次写博客&#xff0c;不喜勿喷。最近一个小师弟问我怎么用Java做图片浏览器&#xff0c;感觉好久没玩Java了&#xff0c;就自己动手做了一下。学校的教程是用Swing来做界面的&#xff0c;所以这里也用这个来讲。首先要做个大概的界面出来&#xff0c;eclipse有一个很好用的…

60. Spring Boot写后感【从零开始学Spring Boot】

从2016年4月15日到2016年7月20日经历长达3个月的时间&#xff0c;【从零开始学习Spring Boot】系列就要告一段落了。国内的各种资源都比较乱或者是copy 来copy去的&#xff0c;错了也不加以修正下&#xff0c;导致通过百度找到的资源可能都是错误的&#xff0c;正是由于这么一种…

五角星

import turtle turtle.setup(600,400,0,0) turtle.bgcolor(red) turtle.color(yellow) turtle.fillcolor(yellow) turtle.begin_fill() for i in range(5):turtle.forward(200)turtle.right(144) turtle.end_fill()turtle.done()转载于:https://www.cnblogs.com/Paris-YY/p/900…

java customerservlet_顾客管理系统java+servlet

首先我先搭好网页的框架先写一个登陆的html&#xff0c;名字是login.html1)在js中跳转页面的方法&#xff0c;我这里用的是get提交&#xff0c;只传递了一个name。function mylogin() {var usernamedocument.getElementById("name").value;window.location.href"…

php输出数据过大,PHPExcel导出数据量过大处理

转&#xff1a;ASP&period;NET MVC3 Model验证总结http://www.wyjexplorer.cn/Post/2012/8/3/model-validation-in-aspnet-mvc3 ASP.NET MVC3中的Model是自验证的,这是通 ...C&plus;&plus; 我想这样用(六)嗯,上一篇已经介绍了面向过程编程的语法知识,接下来是最后的…

计算球面上经纬度坐标方法比较

计算球面上的两点(坐标为经纬度)之间的距离可以直接通过公式计算得到&#xff0c;也可以先将经纬度坐标转化为墨卡托投影坐标来,然后用平面中两点之间的距离公式来计算。 在网上找了一些代码&#xff0c;然后简单进行了测试&#xff0c;发现前者精度更高&#xff1a; 资料来源&…

mysql给root开启远程访问权限,修改root密码

1.MySql-Server 出于安全方面考虑只允许本机(localhost, 127.0.0.1)来连接访问. 这对于 Web-Server 与 MySql-Server 都在同一台服务器上的网站架构来说是没有问题的. 但随着网站流量的增加, 后期服务器架构可能会将 Web-Server 与 MySql-Server 分别放在独立的服务器上, 以便得…

Docker - Docker中搭建MySQL主从

1.pull完centos7纯净版的镜像后&#xff0c;创建容器&#xff0c;然后将宿主机上下载的MySQL文件 (MySQL下载地址&#xff1a;http://mysql.mirror.kangaroot.net/Downloads/) 拷贝到Docker容器中。 1) 抓取centos7纯净版镜像# docker pull registry.cn-hangzhou.aliyuncs.com/…

java 上传远程图片,java上传图片到另一台服务器上,怎么解决

Java codepublic String upload(String dir, FormFile formFile) throws Exception {Date date new Date();//取欲上传的文件的名字和长度String fname formFile.getFileName();//将上传时间加入文件名int i fname.indexOf(".");String name String.valueOf(date…