GUI自动化测试初探

1 Selenium 的实现原理

Selenium
V1.0 核心是Selenium RC
V2.0 核心是WebDriver
V3.0 与2.0相比没有本质的变化,主要是增加了对Mac OS的Safri浏览器和Windows 的Edge 浏览器的支持,并彻底删除了对 Selenium RC 的支持。

1.1 Selenium 1.0

Selenium 1.0,又称为Selenium RC,Remote Control。
Selenium RC的原理是:

同源政策:只有来自相同域名、端口和协议的JavaScript代码才能被浏览器执行。

在测试用例运行的浏览器中注入JavaScript代码从而实现自动化的Web操作,Selenium需欺骗被测站点。
引入Selenium RC Server的根本原因,其中的Proxy模块就是用来欺骗浏览器的。

除Selenium RC服务器之外,Selenium RC提供的另一大部分就是客户端。
GUI自动化测试初探_第1张图片

Selenium Core,是被注入浏览器页面中的JavaScript函数集合,用来实现界面元素的识别和操作
HTTP Proxy,作为代理服务器修改JavaScript的源,以达到欺骗被测站点的目的。
Launcher,用来在启动测试浏览器时完成Selenium Core的注入和浏览器代理的设置。

客户端库,是测试用例代码向Selenium RC Server发送HTTP请求的接口。

Selenium RC执行流程:
1、测试用例通过基于不同语言的客户端库向Selenium RC服务器发送HTTO请求,要求与其建立连接。
2、连接建立后,Selenium RC 服务器的Launcher就会启动浏览器,把Selenium Core(Javascript函数的集合)加载到浏览器页面中,并同时把浏览器的代理设置为HTTP Proxy。
3、测试用例通过客户端库向Selenium RC服务器发送HTTP 请求,Selenium RC 服务器解析请求,然后通过HTTP Proxy发送JavaScript 命令,通知Selenium Core 执行浏览器上控件的具体操作。
4、Selenium Core收到指令后,执行操作。
5、如果浏览器收到新的页面请求信息,则会发送HTTP请求来请求新的Web页面。因为Launcher在启动浏览器时把HTTP Proxy设置成了浏览器的代理,所以Selenium RC服务器会收到所有由他启动的浏览器发送的请求。
6、Selenium RC服务接收到浏览器发送的HTTP请求后,重组HTTP请求以规避”同源策略“,然后获取对应的Web界面。
7、HTTP Proxy把接收的Web页面返回给浏览器,浏览器对接收的页面进行渲染。

1.2 Selenium 2.0

Selenium 2.0又称Selenium WebDriver ,它的原理是使用浏览器原生的WebDriver实现页面操作,实现方式完全不同于1.0.
Selenium 2.0是典型的服务器-客户端模式。
服务端就是远程服务器。
GUI自动化测试初探_第2张图片

WebDriver与之前Selenium的JS注入实现不同,直接利用了浏览器native support来操作浏览器。所以对于不同平台,不同的浏览器,必须依赖一个特定的浏览器的native component来实现把WebDriver API的调用转化为浏览器的native invoke

在我们new一个WebDriver的过程中,Selenium首先会确认浏览器的native component是否存在可用而且版本匹配。接着就在目标浏览器里启动一整套Web Service,这套Web Service使用了Selenium自己设计定义的协议,名字叫做The WebDriver Wire Protocol。这套协议非常之强大,几乎可以操作浏览器做任何事情,包括打开、关闭、最大化、最小化、元素定位、元素点击、上传文件等等等等。
1、当使用Selenium 2.0启动Web浏览器时,后台会同时启动基于WebDriver Wire协议的Web服务作为Selenium的远程服务器,并将其与之绑定。绑定完成后,远程服务器就开始监听客户端的操作请求。
2、执行测试时,测试用例会作为客户端,将需要执行的页面请求以HTTP请求的方式发送给远程服务器,该HTTP请求的正文会以WebDriver Wire 协议规定的JSON格式来 描述需要浏览器执行的 具体操作。
3、远程服务器接收到请求后,会对请求进行解析,并将解析结果发给WebDriver,由WebDriver实际执行浏览器的操作。
4、WebDriver可以看作直接操作浏览器的原生组件,所以搭建测试环境时,通常需要下载对应的WebDriver.

1.3 Selenium 3.0

1、3.0版本的API向下兼容2.0。
2、JDK环境需要升级到JDK1.8或者以上。
3、移除1.0版本的RC。

如果需要测试新版本的Firefox,edge,safri浏览器,使用3.0.
若主要测试Chrome浏览器,2.0稳定性会更好。

2 效率为王:测试脚本和测试数据的解耦

2.1 数据驱动测试

测试数据与测试脚本分离
测试脚本只有一份,输入数据单独存放在一个文件,通常为CSV文件。还支持XLS、JSON、YAML文件。

数据驱动的测试的数据文件中不仅可以包含测试输入数据,还可以包含测试验证结果数据,甚至还可以包含测试逻辑分支的控制变量

数据驱动测试的思想可被应用与API测试、接口测试、单元测试。
故很多API测试工具(如SoapUI Postman),以及单元测试框架(TestNG、Junit)都支持数据驱动测试。

通过测试数据提供程序模块将外部测试数据源逐条喂给测试脚本。

3 效率为王:页面对象模型

页面对象模型的核心理念是,以页面为单位来封装页面 上的控件以及控件的部分操作。
而测试用例(更确切的说是操作函数),基于页面封装对象来完成具体的界面操作。

4 更接近业务的抽象:让自动化测试脚本更好地描述业务

在引入操作函数封装时,操作函数在改善测试脚本可读性问题是,也引入了两个新问题。
1、如何把控操作函数的粒度。
2、以及如何衔接两个操作函数之间的页面。

4.1 操作函数的粒度把控

高内聚低耦合,结合业务流程。

4.2 衔接两个操作函数间的页面

完成一个业务流程操作,往往会需要依次调用多个操作函数,但是操作函数和操作函数之间会有页面粒度的把控,即前序操作函数完成后的最后一个页面,必须是后序操作函数的第一个页面。
如果连续的两个操作函数之间无法用页面衔接,就需要在两个操作函数之间加入额外的页面跳转代码,或者在操作函数内部加入特定的页面跳转代码。

4.3 业务流程抽象

独立的业务流程一般作为独立的类进行封装。
类的内部实现通常是调用操作函数。
操作对象的内部则基于页面对象模型完成具体的页面控件操作。

对于每一个业务流程类,都会有相应的业务流程输入参数类与之一一对应。

具体步骤如下:
1、初始化一个业务流程输入参数类的实例。
2、给这个实例赋值。
3、用这个输入参数类的实例来初始化***业务流程类***的实例。
4、执行这个业务流程实例。

业务流程的优点:
1、业务流程的封装更接近实际业务。
2、基于业务流程的测试用例非常标准化,遵循准备参数、实例化流程和执行流程这3个步骤,非常适用于测试代码的自动生成。
3、因为更接近实际业务,所以可以很方便地和行为驱动开发(BDD)相结合。

5 过不了的坎:GUI自动化过程中的测试数据

为了顺利进行GUI测试,往往需要准备测试数据来配合测试的进行,如果不采用事先准备的方式,测试效率将会大打折扣,而且还会引入大量不必要的依赖关系。
GUI测试中两种常见的数据类型:
1、测试输入数据,也就是GUI测试测试中通过界面输入的数据。
2、为了完成GUI测试而需要准备的测试数据。

创建测试数据的方法主要分为3种:
1、API调用
2、数据库调用
3、综合运用API调用和数据库操作。

实际项目中,要创建测试数据,最佳的选择是利用API
只有当API不能满足数据创建的需求时,才会使用数据库操作的手段。
实际上,往往很多测试数据的创建基于API和数据库两者结合来完成,即先通过API创建基本的数据,然后通过调用数据库操作来修改数据,以满足对测试数据的特定要求。

从创建的时机来讲,创建测试数据的方法主要分为两种:
1、在用例执行过程中,实时创建测试数据;
2、测试用例执行前,实现创建测试数据。

实际项目中,两者结合来使用。

相对稳定的数据类型,比如商品类型,事先创建好,以提高效率。
对于那些一次性的测试数据,如商品、订单、优惠券等,往往采用实时创建测试数据的方式。以保证不存在脏数据。

5.1 基于API调用创建测试数据

对于互联网产品。尤其是现在大量采用微服务架构的网站,API往往以Web服务的方式暴露接口。测试者可以直接调用这个API来创建测试数据,而无需通过前端页面向后台提交表单。
测试数据的准确性由产品API保证,缺点是 并不是所有的测试数据都由相关的API来支持。
另外,需要大量创建数据的测试来说,基于API调用方式的 执行效率即使采用并发机制也不会太理想。
为了解决执行效率的问题,就有了基于数据库操作的测试数据创建手段。

5.2 基于数据库操作创建测试数据

实际项目中,并不是所有的测试数据都可以通过API的方式实现创建和修改,很多数据的创建和修改直接在产品代码内完成,而且并没有对外暴露供测试使用的接口。

把创建和修改数据的相关SQL语句封装成测试数据工具,以方便测试用例的使用。
找到正确的sql语句来创建和修改数据有以下两种方式:
1、手工方式。查阅设计文档和产品代码,找到相关的sql语句集合,或者,直接像开发人员索要相关的sql语句集合。
2、自动方式。在测试方式中,在只有一个活跃用户的情况下,首先通过GUI操作完成测试数据的创建、修改,然后利用数据库监控工具获取这段时间内所有的业务修改记录,一次作为依据开发SQL语句集。

优点:可以创建API不支持的测试数据,并且效率高于API调用方法。
缺点:对于数据库表中结构以及字段的任何变更,都必须同步更新测试工具中的sql语句。
在实际项目中,经常出现因为sql语句不及时更新而导致测试数据错
误的问题。

在实际项目,需要引入测试数据工具的版本管理,并通过开发流程来保证SQL的变更能够及时通知到测试数据工具团队。

5.3 综合运用API调用和数据库操作创建测试数据

5.4 实时创建测试数据

不依赖被测系统中的任何原有数据,也不会对原有数据产生影响,可以从数据层面隔离测试用例,让测试用例中的测试数据实现自包含
但存在以下三个问题
1、测试用例执行时间变长。
2、业务数据的连带关系,导致测试数据的创建效率非常低。
3、实时创建测试数据的方式对测试环境的依赖性很强。

5.5 事先创建测试数据

事先创建测试数据就是在被测系统中预先创建好充足的、典型的测试数据。

这些数据通常是在搭建测试环境时通过数据库脚本"预埋"在系统中的,后续的测试用例中可以直接使用。

缺点:
1、测试用例中需要硬编码测试数据,额外引入了测试数据和用例之间的依赖。
2、一次性的测试数据不适合事先创建测试数据的方法。
测试用例往往需要修改测试数据,而且有些测试数据只能使用一一次(优惠券)。
需要做全局测试数据管理,否则容易因为测试数据失效而造成测试失败。
3、预埋的测试数据可靠性远不如实时创建的数据。
在测试用例的执行过程中,经常会出现测试数据被意外修改的情况。
手动测试或自动化测试用例的调试等,都会修改或者使用这些预埋的数据。

5.6 实时创建测试数据和事先创建测试数据的互补。

1、对于相对稳定、很少修改的数据建议使用事先创建数据的方式。

2、对于经常修改、状态经常发生变化的一次性数据,建议采用实时创建测试数据。

3、当用实时创建测试数据的方式创建测试数据时,上游数据的创建可以采用事先创建测试数据方式,以提高测试效率。

订单数据为例,订单实时创建,卖家、买家、商品事先创建。

6 自动生成页面对象、测试数据、无头浏览器

6.1 自动生成页面对象

页面对象模型就是以Web页面为单位来封装页面上的控件和控件的部分操作,而测试用例基于页面对象完成具体操作。

最典型的模式就是 XXXPage.YYYComponent.ZZZOperation.

页面自动生成技术,非常适用于需要维护大量页面对象的中大型自动化测试项目。
基本思路时:不需要再手动维护Page类了,只需要提供Web的URL,它就会自动生成这个页面上所有控件的定位信息,并自动生成page类。
但需要注意的是,那些依赖于数据的动态页面对象通常不应该包含在page类中,所以需要手动方式删除。
很多商用的自动化工具(UTF)已经支持页面对象的自动生成了,同时还支持对page类进行版本管理。

但是在开源的自动化方案中,页面对象自动生成功能一般需要自己开发,并且需要与测试者所用的自动化测试框架深度绑定

6.2 自动生成GUI测试数据

1、根据GUI输入类型,以及对应的自定义规则库自动生成测试输入数据。
2、多输入数据场景,笛卡尔积组合后人工剔除非法数据。

6.3 无头浏览器简介

是一种没有界面的浏览器,可以简单的把它想象成运行在内存中的浏览器。它拥有完整的浏览器内核,包括JavaScript解析引擎,渲染引擎等。
与普通的浏览器最大的不同是无头浏览器在运行过程中看不到界面,但是依然可以用GUI测试框架的截图功能截取其中的界面。
无头浏览器的主要应用场景包括GUI自动化测试、页面监控以及网络爬虫这3种。
优点:
1、测试速度更快。
2、减少对测试的干扰。可以减少操作系统和其他软件(如杀毒软件)中不可预期的弹出框对浏览器测试的干扰。
3、简化测试执行环境的搭建。
对于大量测试用例的执行而言,可以减少大规模Selenium Grid集群的依赖。
同时GUI测试可以直接运行在无界面的服务器上。
4、在单机环境下实现测试的并发执行。运行多个无头浏览器。

7 提高GUI测试稳定性的关键技术

导致GUI测试不稳定的五个因素
1、非预计的弹出对话框
2、页面控件属性的细微变化
3、被测系统的A/B测试
4、随机的界面延迟造成控件识别失败
5、测试数据问题。

7.1 非预计的弹出对话框

具体做法如下:
1、当自动化测试脚本发现控件无法正确定位时或者无法操作时,GUI自动化框架自动进入”异常场景恢复模式“
2、在”异常场景恢复模式“下,立即执行预定义的操作(比如,点击”确定“按钮,关闭这个对话框),接着重试刚才失败的步骤。
只能处理已知的对话框。
对于新类型的对话框,只能通过自动化的方式尝试单机上面的按钮进行处理。
每当发现一种潜在的弹出的对话框,就把它的详细信息(包括对象定位信息)更新到异常场景恢复中。
异常场景恢复库通常不会采用硬编码的方式来实现,而通过配置库的方式来实现。

7.2 页面控件属性的细微变化

button id 从 button_login_1 编程button_login_888
模糊匹配技术,通过特定的相似度算法,当控件属性发生变化时,这个控件依旧可以被准确定位。
开源的GUI自动化测试框架中,模糊匹配需要二次开发。
实现思路是实现自己的对象识别控制层。不把模糊匹配逻辑以硬编码的形式写入代码里,而是引入规则引擎,将具体的规则以配置文件的方式与代码逻辑解耦。

7.4 随机的页面延迟而造成控件识别失败

加入重试机制,开源自动化测试框架需要二次开发,重试机制可分为三个级别:步骤、页面、业务流程。

7.5 测试数据问题

测试用例所依赖的数据被其他用例修改了。
测试过程中发生错误后自动进行了重试操作,但数据状态已经在第一次执行中被修改了。

8 测试报告

以后补充

9 测试策略设计

以后补充

你可能感兴趣的:(测试)