You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
10 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 12 | 从0到1你的第一个GUI自动化测试
在前面的测试基础知识系列文章中,我分享了测试相关的基础知识,从测试用例的设计,到测试覆盖率,再到测试计划的制定,这些都是我认为测试人要掌握的一些基本知识。
那么接下来我将要带你走入GUI自动化测试的世界和你一起聊聊GUI自动化测试的技术、原理和行业最佳实践。
作为该系列的第一篇文章我直接以一个最简单的GUI自动化用例的开发为例带你从0开始构建一个Selenium的GUI自动化测试用例。
先让你对GUI自动化测试有一个感性认识然后以此为基础我再来解释Selenium自动化测试实现的核心原理与机制希望可以帮你由点到面建立起GUI测试的基础知识体系。
## 构建一个Selenium自动化测试用例示例
测试需求非常简单:访问百度主页,搜索某个关键词,并验证搜索结果页面的标题是“被搜索的关键词”+“\_百度搜索”。
如果搜索的关键词是“极客时间”,那么搜索结果页面的标题就应该是“极客时间\_百度搜索”。
明白了测试需求后,我强烈建议你先用手工方式执行一遍测试,具体步骤是:
1. 打开Chrome浏览器输入百度的网址“[www.baidu.com](http://www.baidu.com)”;
2. 在搜索输入框中输入关键词“极客时间”并按下回车键;
3. 验证搜索结果页面的标题是否是“极客时间\_百度搜索”。
明确了GUI测试的具体步骤后我们就可以用Java代码基于Selenium实现这个测试用例了。
这里我要用到Chrome浏览器所以需要先下载Chrome Driver并将其放入环境变量。接下来你可以用自己熟悉的方式建立一个空的Maven项目然后在POM文件中加入Selenium 2.0的依赖如图1所示。
![](https://static001.geekbang.org/resource/image/83/a3/838b15ae28b8e318577705f61d619aa3.png)
图1 在POM文件中加入Selenium 2.0的依赖
接着用Java创建一个main方法并把如图2所示的代码复制到你的main方法中。
![](https://static001.geekbang.org/resource/image/d4/fb/d4c851bf536ce1fa6167afa169ab8bfb.png)
图2 基于Selenium的自动化测试用例的样本代码
现在你可以尝试运行这个main方法看看会执行哪些操作。
1. 这段代码会自动在你的电脑上打开Chrome浏览器
2. 在URL栏自动输入“[www.baidu.com](http://www.baidu.com)”;
3. 百度主页打开后,在输入框自动输入“极客时间”并执行搜索;
4. 返回搜索结果页面;
5. Chrome浏览器自动退出。
以上这些步骤都是由自动化测试代码自动完成的。
如果你已经接触过GUI自动化测试你可能习以为常了感觉没什么神奇的。但如果你是第一次接触GUI自动化测试是不是觉得还蛮有意思的。
现在,我来快速解读一下这些代码,你可以看看这些自动化步骤是怎么实现的,更具体的原理和内部机制我会在后面文章中详细展开。
* 第11行WebDriver driver = new ChromeDriver()先创建一个Chrome Driver的实例也就是打开了Chrome浏览器但实际上没这么简单后台还做了些额外的Web Service绑定工作具体后面会解释
* 第14行driver.navigate().to(s: “[http://www.baidu.com](http://www.baidu.com)”)用刚才已经打开的Chrome浏览器访问百度主页
* 第18行WebElement search\_input = driver.findElement([By.name](http://By.name)(“wd”))使用driver的findElement方法并通过name属性定位到了搜索输入框并将该搜索输入框命名为search\_input
* 第21行search\_input.sendKeys(…charSequences:“极客时间”)通过WebElement的sendKeys方法向搜索输入框search\_input输入了字符串“极客时间”
* 第24行search\_input.submit(),递交了搜索请求;
* 第27行Thread.sleep(millis:3000)强行等待了固定的3秒时间
* 第30行Assert.assertEquals(expected:“极客时间\_百度搜索”,driver.getTitle())通过junit的assertEquals比较了浏览器的标题与预计结果其中页面标题通过driver的getTitle方法得到如果标题与预计结果一致测试通过否则测试失败
* 第33行driver.quit()显式关闭了Chrome浏览器。
现在你对main方法中的代码已经比较清楚了。但是你知道Selenium内部是如何实现Web自动化操作的吗这就要从Selenium的历史版本和基本原理开始讲起了。
## 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 ServerSelenium RC方案的另一大部分就是Client Libraries。它们的具体关系如图3所示。
![](https://static001.geekbang.org/resource/image/30/b6/30bb6d776cd499b727d83fa4499ca9b6.png)
图3 Selenium RC的基本模块
**Selenium RC Server主要包括Selenium CoreHttp Proxy和Launcher三部分**
* Selenium Core是被注入到浏览器页面中的JavaScript函数集合用来实现界面元素的识别和操作
* Http Proxy作为代理服务器修改JavaScript的源以达到“欺骗”被测站点的目的
* Launcher用来在启动测试浏览器时完成Selenium Core的注入和浏览器代理的设置。
**Client Libraries是测试用例代码向Selenium RC Server发送Http请求的接口支持多种语言**包括Java、C#和Ruby等。
为了帮你更好地理解Selenium RC的基本原理我从Selenium的官方网站截取了以下执行流程图并把具体的7个步骤做了如下翻译。
![](https://static001.geekbang.org/resource/image/9c/69/9c8317d792a8798b3f2cdedf80ff2e69.png)
图4 Selenium RC的执行流程
1. 测试用例通过基于不同语言的Client Libraries向Selenium RC Server发送Http请求要求与其建立连接。
2. 连接建立后Selenium RC Server的Launcher就会启动浏览器或者重用之前已经打开的浏览器把Selenium CoreJavaScript函数的集合加载到浏览器页面当中并同时把浏览器的代理设置为Http Proxy。
3. 测试用例通过Client Libraries向Selenium RC Server发送Http请求Selenium RC Server解析请求然后通过Http Proxy发送JavaScript命令通知Selenium Core执行浏览器上控件的具体操作。
4. Selenium Core接收到指令后执行操作。
5. 如果浏览器收到新的页面请求信息则会发送Http请求来请求新的Web页面。由于Launcher在启动浏览器时把Http Proxy设置成为了浏览器的代理所以Selenium RC Server会接收到所有由它启动的浏览器发送的请求。
6. Selenium RC Server接收到浏览器发送的Http请求后重组Http请求以规避“同源策略”然后获取对应的Web页面。
7. 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工作原理的解析。
![](https://static001.geekbang.org/resource/image/55/26/5536bccaa266329c324fa9033ee16826.png)
图5 Selenium WebDriver的执行流程
1. 当使用Selenium2.0启动浏览器Web Browser时后台会同时启动基于WebDriver Wire协议的Web Service作为Selenium的Remote Server并将其与浏览器绑定。绑定完成后Remote Server就开始监听Client端的操作请求。
2. 执行测试时测试用例会作为Client端将需要执行的页面操作请求以Http Request的方式发送给Remote Server。该HTTP Request的body是以WebDriver Wire协议规定的JSON格式来描述需要浏览器执行的具体操作。
3. Remote Server接收到请求后会对请求进行解析并将解析结果发给WebDriver由WebDriver实际执行浏览器的操作。
4. 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自动化测试框架你知道它们的内部实现原理吗
欢迎你给我留言。