时长11:00大小5.04M
在前面的测试基础知识系列文章中,我分享了测试相关的基础知识,从测试用例的设计,到测试覆盖率,再到测试计划的制定,这些都是我认为测试人要掌握的一些基本知识。
那么,接下来我将要带你走入 GUI 自动化测试的世界,和你一起聊聊 GUI 自动化测试的技术、原理和行业最佳实践。
作为该系列的第一篇文章,我直接以一个最简单的 GUI 自动化用例的开发为例,带你从 0 开始构建一个 Selenium 的 GUI 自动化测试用例。
先让你对 GUI 自动化测试有一个感性认识,然后以此为基础,我再来解释 Selenium 自动化测试实现的核心原理与机制,希望可以帮你由点到面建立起 GUI 测试的基础知识体系。
测试需求非常简单:访问百度主页,搜索某个关键词,并验证搜索结果页面的标题是“被搜索的关键词”+“_ 百度搜索”。
如果搜索的关键词是“极客时间”,那么搜索结果页面的标题就应该是“极客时间 _ 百度搜索”。
明白了测试需求后,我强烈建议你先用手工方式执行一遍测试,具体步骤是:
打开 Chrome 浏览器,输入百度的网址“www.baidu.com”;
在搜索输入框中输入关键词“极客时间”并按下回车键;
验证搜索结果页面的标题是否是“极客时间 _ 百度搜索”。
明确了 GUI 测试的具体步骤后,我们就可以用 Java 代码,基于 Selenium 实现这个测试用例了。
这里,我要用到 Chrome 浏览器,所以需要先下载 Chrome Driver 并将其放入环境变量。接下来,你可以用自己熟悉的方式建立一个空的 Maven 项目,然后在 POM 文件中加入 Selenium 2.0 的依赖,如图 1 所示。
接着用 Java 创建一个 main 方法,并把如图 2 所示的代码复制到你的 main 方法中。
现在,你可以尝试运行这个 main 方法,看看会执行哪些操作。
这段代码会自动在你的电脑上打开 Chrome 浏览器;
在 URL 栏自动输入“www.baidu.com”;
百度主页打开后,在输入框自动输入“极客时间”并执行搜索;
返回搜索结果页面;
Chrome 浏览器自动退出。
以上这些步骤都是由自动化测试代码自动完成的。
如果你已经接触过 GUI 自动化测试,你可能习以为常了,感觉没什么神奇的。但如果你是第一次接触 GUI 自动化测试,是不是觉得还蛮有意思的。
现在,我来快速解读一下这些代码,你可以看看这些自动化步骤是怎么实现的,更具体的原理和内部机制我会在后面文章中详细展开。
现在,你对 main 方法中的代码,已经比较清楚了。但是,你知道 Selenium 内部是如何实现 Web 自动化操作的吗?这就要从 Selenium 的历史版本和基本原理开始讲起了。
首先,你要明确刚才建立的测试用例是基于 Selenium 2.0,也就是 Selenium + WebDriver 的方案。
其次,你需要知道,对 Selenium 而言,V1.0 和 V2.0 版本的技术方案是截然不同的,V1.0 的核心是 Selenium RC,而 V2.0 的核心是 WebDriver,可以说这完全是两个东西。
最后,Selenium 3.0 也已经发布一段时间了,V3.0 相比 V2.0 并没有本质上的变化,主要是增加了对 MacOS 的 Safari 和 Windows 的 Edge 的支持,并彻底删除了对 Selenium RC 的支持。
所以接下来,我会针对 V1.0 和 V2.0 来解释 Selenium 实现 Web 自动化的原理。
第一,Selenium 1.0 的工作原理
Selenium 1.0,又称 Selenium RC,其中 RC 是 Remote Control 的缩写。Selenium RC 利用的原理是:JavaScript 代码可以很方便地获取页面上的任何元素并执行各种操作。
但是因为"同源政策(Same-origin policy)"(只有来自相同域名、端口和协议的 JavaScript 代码才能被浏览器执行),所以要想在测试用例运行中的浏览器中,注入 JavaScript 代码从而实现自动化的 Web 操作,Selenium RC 就必须“欺骗”被测站点,让它误以为被注入的代码是同源的。
那如何实现“欺骗”呢?这其实就是引入 Selenium RC Server 的根本原因,其中的 Http Proxy 模块就是用来“欺骗”浏览器的。
除了 Selenium RC Server,Selenium RC 方案的另一大部分就是,Client Libraries。它们的具体关系如图 3 所示。
Selenium RC Server,主要包括 Selenium Core,Http Proxy 和 Launcher 三部分:
Client Libraries,是测试用例代码向 Selenium RC Server 发送 Http 请求的接口,支持多种语言,包括 Java、C# 和 Ruby 等。
为了帮你更好地理解 Selenium RC 的基本原理,我从 Selenium 的官方网站截取了以下执行流程图,并把具体的 7 个步骤做了如下翻译。
测试用例通过基于不同语言的 Client Libraries 向 Selenium RC Server 发送 Http 请求,要求与其建立连接。
连接建立后,Selenium RC Server 的 Launcher 就会启动浏览器或者重用之前已经打开的浏览器,把 Selenium Core(JavaScript 函数的集合)加载到浏览器页面当中,并同时把浏览器的代理设置为 Http Proxy。
测试用例通过 Client Libraries 向 Selenium RC Server 发送 Http 请求,Selenium RC Server 解析请求,然后通过 Http Proxy 发送 JavaScript 命令通知 Selenium Core 执行浏览器上控件的具体操作。
Selenium Core 接收到指令后,执行操作。
如果浏览器收到新的页面请求信息,则会发送 Http 请求来请求新的 Web 页面。由于 Launcher 在启动浏览器时把 Http Proxy 设置成为了浏览器的代理,所以 Selenium RC Server 会接收到所有由它启动的浏览器发送的请求。
Selenium RC Server 接收到浏览器发送的 Http 请求后,重组 Http 请求以规避“同源策略”,然后获取对应的 Web 页面。
Http Proxy 把接收的 Web 页面返回给浏览器,浏览器对接收的页面进行渲染。
第二,Selenium 2.0 的工作原理
接下来,我们回到上面那个百度搜索的测试用例,这个测试用例用的就是 Selenium 2.0。Selenium 2.0,又称 Selenium WebDriver,它利用的原理是:使用浏览器原生的 WebDriver 实现页面操作。它的实现方式完全不同于 Selenium 1.0。
Selenium WebDriver 是典型的 Server-Client 模式,Server 端就是 Remote Server。以下是 Selenium 2.0 工作原理的解析。
当使用 Selenium2.0 启动浏览器 Web Browser 时,后台会同时启动基于 WebDriver Wire 协议的 Web Service 作为 Selenium 的 Remote Server,并将其与浏览器绑定。绑定完成后,Remote Server 就开始监听 Client 端的操作请求。
执行测试时,测试用例会作为 Client 端,将需要执行的页面操作请求以 Http Request 的方式发送给 Remote Server。该 HTTP Request 的 body,是以 WebDriver Wire 协议规定的 JSON 格式来描述需要浏览器执行的具体操作。
Remote Server 接收到请求后,会对请求进行解析,并将解析结果发给 WebDriver,由 WebDriver 实际执行浏览器的操作。
WebDriver 可以看做是直接操作浏览器的原生组件(Native Component),所以搭建测试环境时,通常都需要先下载浏览器对应的 WebDriver。
首先,我基于 Selenium 2.0,带你从 0 到 1 建立了一个最简单直接的 GUI 自动化测试用例。这个用例的实现很简单,但是只有真正理解了 Selenium 工具的原理,你才能真正用好它。
所以,我又分享了 Selenium 1.0 和 Selenium 2.0 的内部实现机制和原理:Selenium 1.0 的核心是,基于 JavaScript 代码注入;而 Selenium 2.0 的核心是,运用了浏览器原生支持的 WebDriver。
除了 Selenium,业内还有很多常用的 GUI 自动化测试框架,比如 UFT(以前的 QTP)、RFT、Nightwatch 等,你在平时的工作中接触过哪些 GUI 自动化测试框架?你知道它们的内部实现原理吗?
欢迎你给我留言。
作者回复: 你说的非常对,1.0基本淘汰了,重点是2.0,3.0的核心原理是个2.0一样的👍
作者回复: 你提的建议非常棒,下一篇文章就会讨论这些话题,第一篇只是给出一个最基本的gui用例,让刚入门的同学有个感性的认识
作者回复: 不同的浏览器需要下载对应的driver
作者回复: 总结的很到位,你说的这些问题我也都遇到过,要做gui自动化测试,这些问题都是不可回避的,后续的文章会介绍一些实践可以在一定程度上规避或者减轻这些问题。
作者回复: 不需要了解http网络协议,但是需要了解webdriver的实现原理以及web service的概念
作者回复: 建议通过inspector观察需要定位的元素属性,然后再选择你的selector,如果单属性不好定位,也可以考虑使用组合属性
作者回复: 说得很多,对于互联网产品的测试策略往往以api为主,但是前端还是会保留轻量级的自动化来保证最基本功能的回归,同时引入前端的探索式测试以发现更多的潜在问题
作者回复: 推荐官方网站的文档,没必要买书
作者回复: web service目前依旧是主流,一定需要好好掌握
作者回复: 的确是的,webdriver启动的浏览器过程中有很多额外的步骤。如果你的被测软件够简单,简单的录制回放是可以的,但是用例多了维护性的问题就会很严重!