一、设计背景

随着IT行业的发展,产品愈渐复杂,web端业务及流程更加繁琐,目前UI测试仅是针对单一页面,操作量大。为了满足多页面功能及流程的需求及节省工时,设计了这款UI 自动化测试程序。旨在提供接口,集成到蜗牛自动化测试框架,方便用例的设计。

整个程序是基于 selenium 设计的。程序对 selenium 提供的接口进行了二次封装以满足日常的用例设计,二次封装后的接口解决了元素加载,元素定位解析等问题,可以让用例设计变得更加简捷。

之所以采用 Selenium 的模式。原因一,对于用户来说这是一个开源框架,很想窥探一二; 原因二,Selenium 可无缝接入。这是一个用于Web应用程序测试的工具,支持多平台、多浏览器、多语言去实现自动化测试,Selenium2将浏览器原生的API封装成WebDriver API,可以直接操作浏览器页面里的元素,甚至操作浏览器本身(截屏,窗口大小,启动,关闭之类的),所以就像真正的用户在操作一样。

目前支持:Mac、Windows操作系统,chrome、Firefox、IE浏览器。

二、工作原理

  • 在蜗牛管理后台添加测试用例。
  • 蜗牛管理后台测试用例执行调用任务执行接口,传送任务id及测试数据的JSON格式字符串给程序。
  • 程序根据获取数据,解析并处理。
  • 启动浏览器后,selenium-webdriver会将目标浏览器绑定到特定的端口,启动后的浏览器则作为webdriver的server。
  • 客户端(也就是测试脚本),借助ComandExecutor发送HTTP请求给server端(通信协议:The WebDriver Wire Protocol,在HTTP request的body中,会以WebDriver Wire协议规定的JSON格式的字符串来告诉Selenium,我们希望浏览器接下来做什么事情)。
  • Server端需要依赖原生的浏览器组件,转化Web Service的命令为浏览器native的调用来完成操作。
  • 最后将处理结果及任务id通过JSON字符串的格式返回给蜗牛,通过蜗牛的管理后台可查看每条用例执行结果。

三、框架介绍

3.1 工程结构

按照实际的业务流程调用对应接口来实现 WEB-UI 自动化测试用例。case 层可调用 service 层和 pageObject 层的接口,pageObject 是对每一个页面元素的一个封装,service 是对一个常用的业务模块功能的封装。比如一个查询企业信息的测试用例,需要依赖登入,这个业务功能就可以直接调用 service 中的接口。企业查询的创建就可以调用 pageObject 中的接口,然后按照查询的业务流程,在测试用例中把这些接口串起来就形成了一个 UI 自动化测试用例,详细细节接下去会举例说明。

如企业查询。查询之前,需要登入管理后台,登入操作已封装到业务层,直接调用 service 层的接口,不需要在意这个步骤的细节;登入之后要指定一个路径,找到对应的空间,直接调用 model 层的接口,不需要在意这个步骤的细节;接着是创建查询,创建查询的所有定位方法也封装到业务层,这就是个企业查询的实现,也是用例设计中最主要的环节。

整个工程基于 selenium,采用 pageObject 模式搭建。下面对工程中的几个重要模块做介绍。

3.1.1 driver — 接口层

对 web 页面所有元素的操作都是在driver定义接口并实现的。driver 对 selenium 提供的接口做了二次封装,对外提供封装后的接口。pageObject 实现了一些公共方法,比如给输入框赋值等,目前 pageObject封装的方法不多,大多功能都可以通过 selenium 实现。driver 层对开源工具接口做了二次封装,想要驱动一个浏览器还有一个必不可少的工具 —— 浏览器驱动,这个驱动放在 Referenced Libraries 里,驱动的版本必须与被测浏览器版本相匹配。

3.1.2 model — 数据模型

创建数据模型为了实现测试数据和测试用例分离而采取的一种方法,具体的测试数据初始化。可以对一个业务流程中需要测试数据的元素在一个 model 中定义出来,方便管理和代码阅读。

3.1.3 pageObject — 业务层

pageObject 模式,采用接口形式封装每一个页面需要用到的元素,实现封装只要做两步:

  • 确定元素的定位方式;
  • 调用 driver 中对应的操作接口。

driver 的接口实现包含了一定的容错能力,但并不是全面的,部分页面或者组件具有独特性,单纯调用 driver 的接口并不能保证测试用例的稳定性,此时就需要在 pageObject 的接口实现中加入一些容错算法,确保用例稳定性。

3.1.4 service — 提供业务功能

一个业务流程很多时候依赖其他业务模块功能,为了方便设计一个测试用例,也为了避免重复造轮子,service 层就提供了一些常用的业务功能,比如登入、企业查询等。依赖方只需要在 service 层调用即可。

3.2 功能优化

对selenium 做二次封装的同时也对接口做了优化,框架的初衷是使UI 用例的设计尽可能的易设计、易读、易维护。

3.2.1 接口优化

直接调用 selenium 的接口经常会遇到些令人头疼的问题,比如网络问题使页面 loading 太慢,需要操作的元素还没展示出来,这种情况就会经常报元素找不到的 error,导致用例执行失败,但实际上这种报错并不是一个 bug,其测试结果是无效的。为了减少误报率 driver 层接口设计了等待元素加载的功能,使用的关键方法:cf.searchForElementVisibleXpath(TestStartQuitwd.wd, "//*[text()='运营平台登录']", id, 200, 100L)。参考代码:

在 click、input 等操作接口中加入循环查找的判断可最大限度的等待一个元素的加载从而提高测试用例的稳定性。

3.2.2 元素定位统一入口

接触过 UI 自动化用例设计的测试人员会比较清楚,想通过 selenium 操作一个元素,其中必不可少的就是对元素定位的描述,通俗的讲就是要通知接口在当前页面操作哪个位置上的元素。定位一个元素的方法很多,常用的有 id,name,css,xpath 等,对应不同的定位方法selenium 在处理上也给出了不同接口,这从维护角度上来考虑显然不是最好的。最好的做法就是用例设计者只管元素定位和操作事件的调用,而事件在实现上走了哪种渠道最好是无感知,无需维护的。对此框架封装了一个方法供 driver 调用,主要功能就是解析描述元素的字符串自动判断是 id、css 还是 xpath。

3.3 元素定位

UI自动化用例其实可以分成两部分:定位元素;调用接口操作该元素。其中定位一个元素的方法很多,常用的有 id,name,css,xpath。实际设计中选择哪种定位方法一般会在维护角度上考虑的会多一些,因为现在的服务器性能配置等都很优秀,所以跑一个WEB-UI用例可以不用考虑性能问题。从维护成本上考虑会优先选择 id、name,其次 css,最后用 xpath。

我们不能保证每一个 web 系统的所有元素都能提供一个唯一 id 或 name,当然如果能和前端开发达成合作,这就是一件很美好的事情了。一般情况下我们都需要面对没有 id 和 name 这两个属性的情况。这时我们就可以使用 css 样式,很多时候 css 样式是能满足我们的定位需求。当然在这些都不提供给我们的情况下就只能选择 xpath,使用 xpath 的优点:

  • 易获取,主流浏览器只要打开“查看”就可以通过 copy 轻松获取到;
  • 页面上的元素都可以用 xpath 来描述;缺点,不稳定,大量使用会给用例维护产生很大的负担。

xpath 一般只要前端在页面上做一下小调整,用例就必须重新维护,在不得不使用 xpath 的情况下,为了减少今后的维护量,可对 xpath 做一些优化,可以减少 xpath 的路径长度提高稳定性。以下是实践过程中最长用到的几种类型:

  • 依靠自己的属性文本定位,如 //input[@value=‘XXXXX’]
  • 包含指示性字符,如 //input[contains(text(),’指示性字符’)]
  • 巧妙使用content,如 //*[@id=‘app-container']

四、常见报错

使用过程中经常会遇到问题,这里做下总结方便 debug。

  • 某些页面弹窗,有时候定位不到弹窗元素。理论上 selenium 在一个页面中查找一个元素是可以定位到,但有些时候出现弹窗,此时就需要在重新定位弹窗。解决方法:

  • 有些输入框不能被 input 接口正常操作。实践过程中在日历控件中遇到过,元素定位什么的都对,但就是不能正常被操作。解决方法:判断元素是否是select类型,之后再赋值。解决代码:

3.发现 selenium 的某些接口不能 work 了,此时最大的可能就是浏览器升级了。解决方法:重新下载低版本浏览器。

4.元素不可见。有一种元素能在页面上正常展示,但对于工具来说它是不可见的,这是因为在一般情况下,元素可见需要满足以下几个条件:visibility!=hidden ; display!=none; opacity!=0; height、width都大于0;对于 input 标签,没有 hidden 属性。如截图就是只读的实例。

解决方法:调用接口 TestStartQuitwd.js.executeScript("var txtN = document.getElementsByName("timeRange"); txtN[0].readOnly = false;");

五、结束语

UI自动化是在开源工具的基础上做了些优化,在 driver 层,数据层、业务层以及用例层的解决方案还有很大的提升空间。WEB-UI自动化还不完美,后期还需继续努力。感谢一直以来支持研究的小伙伴。

作者:颜博莲

来源:宜信技术学院

WEB-UI自动化测试实践的更多相关文章

  1. 【转】Web UI自动化测试原理

    目前市面上有很多Web UI自动化测试框架,比如WatiN, Selinimu,WebDriver,还有VS2010中的Coded UI等等.  这些框架都可以操作Web中的控件,模拟用户输入,点击等 ...

  2. [原创]浅谈Web UI自动化测试

    [原创]浅谈Web UI自动化测试 Web UI自动化测试相信大家都不陌生,今天来谈谈这个,我最早接触自动化测试时大约是在2004年,2006年当时在腾讯财付通算是开始正式接触自动化测试,之所以是正式 ...

  3. 简单Web UI 自动化测试框架 pyse

    WebUI automation testing framework based on Selenium and unittest. 基于 selenium 和 unittest 的 Web UI自动 ...

  4. Web UI自动化测试中绕开验证码登陆方式浅谈

    web自动化测试中让测试者感到困惑的是登陆验证码,每次都不一样.现在推荐一种绕开验证码登陆的方式,其实就是将web浏览器获取的登陆cookie加载到程序中就可以了,这样程序就会认为你已经登陆,就可以跳 ...

  5. Web UI自动化测试基础——元素定位(三)

    本篇文章整理了元素定位的基础知识——iframe框架中的元素定位. 一.iframe框架元素定位 iframe是Html页面的内联框架,如果在自动化测试中无法定位到某个元素,那么很有可能是因为该元素在 ...

  6. Robot Framework进行web ui自动化测试,浏览器配置说明

    转载请注明出处,谢谢: chrome浏览器: 1.从如下地址下载与本地浏览器版本号一致的chromedriver.exe驱动文件: http://chromedriver.storage.google ...

  7. Web UI自动化测试基础——元素定位(二)

    本篇文章整理了元素定位的基础知识——多个元素定位方式. 一.多个元素定位方式简介 同单个元素定位方式相同,多个元素定位方式也有与之对应的8种方式,即id.name.class_name.tag_nam ...

  8. Web UI自动化测试基础——元素定位(一)

    本篇文章整理了元素定位的基础知识——单个元素定位方式. 一.单个元素定位方式简介 1. find_element_by_id 通过元素的id属性进行定位.以百度首页为例,首先进入https://www ...

  9. Selenide UI 自动化测试

       我没有拼写错误,确实不是 Selenium ,但是,只要是 Web UI 自动化测试框架,基本上都是基于Selenium 的.Selenide 也不例外.那为啥不直接用Selenium呢? 因为 ...

  10. 【Robot Framework 项目实战 02】SeleniumLibrary Web UI 自动化

    前言 SeleniumLibrary 是针对 Robot Framework 开发的 Selenium 库.它也 Robot Framework 下面最流程的库之一.主要用于编写 Web UI 自动化 ...

随机推荐

  1. 用泛型写Redis缓存与数据库操作工具类

    功能描述: 先从缓存获取数据,如果缓存没有,就从数据库获取数据,并设置到缓存中,返回数据. 如果数据库中没有数据,需要设置一个缓存标记flagKey,防止暴击访问数据库,用缓存保护数据库. 当删除缓存 ...

  2. TextView 使用详解

    极力推荐文章:欢迎收藏 Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以 ...

  3. kube-proxy源码分析

    kubernetes离线安装包,仅需三步 kube-proxy源码解析 ipvs相对于iptables模式具备较高的性能与稳定性, 本文讲以此模式的源码解析为主,如果想去了解iptables模式的原理 ...

  4. Netty学习(七)-Netty编解码技术以及ProtoBuf和Thrift的介绍

    在前几节我们学习过处理粘包和拆包的问题,用到了Netty提供的几个解码器对不同情况的问题进行处理.功能很是强大.我们有没有去想这么强大的功能是如何实现的呢?背后又用到了什么技术?这一节我们就来处理这个 ...

  5. 链表:如何实现LRU缓存淘汰算法?

    缓存淘汰策略: FIFO:先入先出策略 LFU:最少使用策略 LRU:最近最少使用策略   链表的数据结构: 可以看到,数组需要连续的内存空间,当内存空间充足但不连续时,也会申请失败触发GC,链表则可 ...

  6. OpenGL入门第一天:环境

    本文是个人学习记录,学习建议看教程 https://learnopengl-cn.github.io/ 非常感谢原作者JoeyDeVries和各位翻译提供的优质教程 近况(牢骚 这几天教母校初中的OI ...

  7. Kafka 系列(五)—— 深入理解 Kafka 副本机制

    一.Kafka集群 Kafka 使用 Zookeeper 来维护集群成员 (brokers) 的信息.每个 broker 都有一个唯一标识 broker.id,用于标识自己在集群中的身份,可以在配置文 ...

  8. linux下搭建LJMT(图文版)

    一.  安装VM14 1.1 安装虚拟机vm14(略) 输入序列号:AC5XK-0ZD4H-088HP-9NQZV-ZG2R4(可自行百度) 二. 安装centos详细步骤 2.1安装centos.( ...

  9. nodejs简单抓包工具

    就是简简单单写程序的我为什么需要抓包? 其实在平时写demo的时候需要用到一些图片和文本的资源的,但是需求量比较大,这个时候就想去网站上面直接复制啊,然后图片另存为啊,什么的一系列繁琐的操作. 但是现 ...

  10. Selenium webdriver工作原理

    webdriver是以server-client 经典模式设计的 server端可以是任何浏览器作为remote server,职责就是处理client的请求并作出相应操作,response的具体内容 ...