12 | 从0到1:你的第一个GUI自动化测试

在前面的测试基础知识系列文章中,我分享了测试相关的基础知识,从测试用例的设计,到测试覆盖率,再到测试计划的制定,这些都是我认为测试人要掌握的一些基本知识。

那么,接下来我将要带你走入GUI自动化测试的世界,和你一起聊聊GUI自动化测试的技术、原理和行业最佳实践。

作为该系列的第一篇文章,我直接以一个最简单的GUI自动化用例的开发为例,带你从0开始构建一个Selenium的GUI自动化测试用例。

先让你对GUI自动化测试有一个感性认识,然后以此为基础,我再来解释Selenium自动化测试实现的核心原理与机制,希望可以帮你由点到面建立起GUI测试的基础知识体系。

构建一个Selenium自动化测试用例示例

测试需求非常简单:访问百度主页,搜索某个关键词,并验证搜索结果页面的标题是“被搜索的关键词”+“_百度搜索”。

如果搜索的关键词是“极客时间”,那么搜索结果页面的标题就应该是“极客时间_百度搜索”。

明白了测试需求后,我强烈建议你先用手工方式执行一遍测试,具体步骤是:

  1. 打开Chrome浏览器,输入百度的网址“www.baidu.com”;

  2. 在搜索输入框中输入关键词“极客时间”并按下回车键;

  3. 验证搜索结果页面的标题是否是“极客时间_百度搜索”。

明确了GUI测试的具体步骤后,我们就可以用Java代码,基于Selenium实现这个测试用例了。

这里,我要用到Chrome浏览器,所以需要先下载Chrome Driver并将其放入环境变量。接下来,你可以用自己熟悉的方式建立一个空的Maven项目,然后在POM文件中加入Selenium 2.0的依赖,如图1所示。

图1 在POM文件中加入Selenium 2.0的依赖

接着用Java创建一个main方法,并把如图2所示的代码复制到你的main方法中。

图2 基于Selenium的自动化测试用例的样本代码

现在,你可以尝试运行这个main方法,看看会执行哪些操作。

  1. 这段代码会自动在你的电脑上打开Chrome浏览器;

  2. 在URL栏自动输入“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”)用刚才已经打开的Chrome浏览器访问百度主页;
  • 第18行,WebElement search_input = driver.findElement(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 Server,Selenium RC方案的另一大部分就是,Client Libraries。它们的具体关系如图3所示。

图3 Selenium RC的基本模块

Selenium RC Server,主要包括Selenium Core,Http Proxy和Launcher三部分:

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

Client Libraries,是测试用例代码向Selenium RC Server发送Http请求的接口,支持多种语言,包括Java、C#和Ruby等。

为了帮你更好地理解Selenium RC的基本原理,我从Selenium的官方网站截取了以下执行流程图,并把具体的7个步骤做了如下翻译。

图4 Selenium RC的执行流程
  1. 测试用例通过基于不同语言的Client Libraries向Selenium RC Server发送Http请求,要求与其建立连接。

  2. 连接建立后,Selenium RC Server的Launcher就会启动浏览器或者重用之前已经打开的浏览器,把Selenium Core(JavaScript函数的集合)加载到浏览器页面当中,并同时把浏览器的代理设置为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工作原理的解析。

图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自动化测试框架?你知道它们的内部实现原理吗?

欢迎你给我留言。

精选留言

  • Cynthia🌸

    2018-07-28 13:53:26

    作者讲述的selenium工作原理,十分清晰有条理。
    而其他教你学自动化测试学selenium的文章或者书籍,重点都在操作api上,或者就直接带你分析源码。而很少先把原理讲清楚,导致不少小伙伴学习并应用了很久,还是不够清楚背后的原理。所以也会看到类似的提问:为啥Chrome可以跑的case,Firefox跑不了,为啥webdriver还要一个浏览器装一个?
    如果先弄清楚原理,就不会再在这些问题上有疑问。
    另外,由于2.0以后webdriver逐渐成为主流,所以个人觉得1.0的原理大概看看有个概念就好了,重点放在2.0上面。
    作者回复

    你说的非常对,1.0基本淘汰了,重点是2.0,3.0的核心原理是个2.0一样的👍

    2018-08-01 07:55:31

  • 图·美克尔

    2018-07-25 12:37:21

    希望能讲一些设计思想,比如我们构建web自动化测试时需要抽象出哪些类比如page oriented的设计,以及为什么这么设计,再就是想了解你们在搭建整个自动化框架的时候是具体使用到哪些模块,比如邮件通知模块以及报告结果模块或者日志模块等等,希望老师能给我们讲解一个业内目前的最佳实践。
    作者回复

    你提的建议非常棒,下一篇文章就会讨论这些话题,第一篇只是给出一个最基本的gui用例,让刚入门的同学有个感性的认识

    2018-07-25 23:20:27

  • Geek_66d7b2

    2021-01-21 09:20:17

    现在好多都是用Python实现的,老师这里用Java甚至有点看不懂
  • soul

    2018-07-25 16:39:53

    值得注意得地方,预先装好浏览器的驱动器,不然会报错 " java.lang.IllegalStateException: The path to the driver executable must be set by the webdriver.chrome.driver system property;大家如果再执行过程中提示如上错误,去这个地址下载即可 https://sites.google.com/a/chromium.org/chromedriver/downloads
    作者回复

    不同的浏览器需要下载对应的driver

    2018-07-25 23:18:36

  • 橄榄

    2018-07-26 08:36:00

    没有做过GUI自动化测试,不过茹老师讲的也能听懂一丢丢
    另外,能否专门讲个手机软件测试的专题,如何用monkey实现自动化,初学者请茹老师谅解
  • 白菜兔

    2020-03-20 07:51:41

    网易推出的airTest。尝试过UI自动化测试,通过录制屏幕操作,执行时基于图像识别,完成测试。
  • 2018-08-01 08:52:14

    近期也整理了一个GUI测试框架,pytest+selenium+allure+jenkins,目前只实现了抽离了公共方法、配置文件、测试数据、页面对象独立,使用上目前倒是没有什么问题,但总感觉还是不够灵活。最关键的是,现在脚本执行效率的问题。最近在研究如何实现脚本分布式运行的方法,但是还没有找到好的解决方案,好像jenkins通过节点实现脚本分割和测试报告归集(难点),不知道作者对脚本分布式运行有没有比较好的方案建议?万分感谢。
  • 阿鼎

    2018-07-27 08:26:22

    请问非web应用的传统gui测试用神马?
    作者回复

    我个人推荐UFT,也就是以前的qtp,文章中的所讲的所以概念和方法对于非web应用也是完全适应的

    2018-07-28 08:31:27

  • C

    2018-07-25 12:48:48

    一直纠结要不要做gui自动化,我遇到的问题有1.前端ui控件开发不统一,不是统一框架来做的ui设计,维护各模块脚本成本高。2.企业没有做单元测试和接口测试,没有信心做ui自动化测试3.ui界面动一动,ui感觉要维护成本较高。也听过别人说要针对ui框架设计UI自动化测试框架,不知道如何实施(目前还停留在ui脚本层)4.uI自动化能做到什么层度?冒烟是必须的,稳定模块的回归测试能否用ui代替,虽然成本高。
    作者回复

    总结的很到位,你说的这些问题我也都遇到过,要做gui自动化测试,这些问题都是不可回避的,后续的文章会介绍一些实践可以在一定程度上规避或者减轻这些问题。

    2018-07-25 23:25:22

  • 红娟

    2018-07-25 07:57:59

    配图很漂亮,颜色丰富的嫩芽。一看心情就很好
    言归正传,我比较熟悉python,电脑里装的是selenium 3,待会儿试着写一下用例的case。重点是背后的实现原理。
    我的问题是,如果需要了解背后的实现原理,是不是需要了解http网络协议?
    作者回复

    不需要了解http网络协议,但是需要了解webdriver的实现原理以及web service的概念

    2018-07-25 23:21:53

  • sylan215

    2019-02-13 18:51:35

    1.提到 Web UI 自动化目前用的最多的肯定还是 selenium 了;

    2.之前也了解了 selenium 1.0 和 2.0 的区别,也对 WebDriver 有了基本的了解,但确实没有本次讲解的这么透彻,给茹老师点赞;

    3.selenium 的入口其实很简单,个人感觉他麻烦的地方还是在用例设计上,比如用例设计的颗粒度,以及对于用例稳定性的考量(用例数据的选取)等;

    以上,欢迎关注公众号「sylan215」一起沟通交流。
  • Jimmie.Zhou

    2018-07-25 21:00:45

    前端修改越来越频繁,到大部分后端api修改较少,通常是新增,所以基于api的自动化测试效果刚加好。
    作者回复

    说得很多,对于互联网产品的测试策略往往以api为主,但是前端还是会保留轻量级的自动化来保证最基本功能的回归,同时引入前端的探索式测试以发现更多的潜在问题

    2018-07-28 08:42:38

  • Middleware

    2020-11-08 13:37:55

    很有用,尝试一下
  • Geek_wenzikaka

    2019-09-15 19:16:43

    最近公司要采用non-selenium的测试框架,原因之一就是selenium速度太慢,所以选择了cypress,但其实我并不十分清楚non-selenium和selenium本质的区别,因为两者在运行时很相似,望老师解惑。谢谢
  • Geek_007

    2019-05-02 04:20:43

    测试电脑桌面端软件 有什么好方案吗?
  • 涟漪852

    2018-11-23 08:05:27

    Selenium的书籍,请老师推荐下(。・ω・。)ノ
    作者回复

    推荐官方网站的文档,没必要买书

    2018-11-29 13:31:45

  • 小老鼠

    2018-10-24 18:33:38

    学习Selenium 1.0原理现在还有意义吗?若有,意义在哪里?
  • Harry Potter

    2018-09-13 07:05:07

    老师您好,请问cs架构项目的gui自动化测试除了QTP之外,还有其他比较好的开源工具吗?QTP是商用的,小一点的公司可能不愿意去花这个钱。
  • Declan

    2018-07-27 08:21:51

    不知道UFT的原理是什么,它有很多元素定位的方式
    作者回复

    uft支持多动不同的元素定位方式,有些原理类似,比如对象仓库的元素,都是基于属性或者属性的组合,还有一些所谓的低级录制,那就是基于图像识别的,更具体的需要参考uft的官方文档,这块有很多内容

    2018-07-28 08:34:17

  • 塔矢亮的小螃蟹

    2018-07-26 07:51:10

    刚入门自动化测试的小白想问一个很菜鸟的问|・ω・`)
    我最近在看虫师的一本自动化测试的书来学习,用的是python+selenium,但是在元素定位这里一直受到了打击,要是定位按钮,链接都没问题,但是定位输入框比如说登录界面的输入框,用了各种办法xpath,css定位都说找不到这个元素,哦,我用的是chrome的插件xpath helper来自动生成xpath,按道理应该是没错的呀,一直非常困惑
    作者回复

    建议通过inspector观察需要定位的元素属性,然后再选择你的selector,如果单属性不好定位,也可以考虑使用组合属性

    2018-07-28 08:40:21