申明:本文章转载 殷坤

自动化测试 - 前言

在本系列的第一篇文章 “我们的测试为什么不够敏捷” 中,根据实例总结出敏捷自动化测试的两大阻碍:“脚本维护困难”、“断言条件繁琐”。本文针对在不失自动化测试有效性的前提下如何降低断言成本来分享一些实践经验。

目前业界常见的自动化测试工具在断言方面大多都是采用 “指哪儿打哪儿” 的细粒度模式,即,在自动化测试过程中只能对设置为断言条件的字段(页面元素)进行断言。而且这些测试工具即使提供录制脚本的功能,但对于断言往往还需要测试人员手工补充插入。

除了补充、维护断言条件的工作量大之外,这种断言模式还存在一些明显的不足,下面结合一个实际的例子(如下图)进行分析:

无法感知未设为断言对象的字段上发生的错误

以上图为例,如果在 “增加用户” 的测试脚本之后只对列表中的 “用户姓名是否存在” 进行断言,那么就可能遗漏 “入职日期没有提交成功” 的错误。而且由于页面的信息量往往很大,我们是不可能对所有字段都设置为断言条件的。

难以对于 UI 样式或 UI 逻辑进行断言

以上图为例,有一个 UI 样式类的缺陷(左侧菜单树的根节点 “console” 下面多出来一条虚 线)和一个 UI 逻辑类的缺陷(右侧用户列表只有一页,但 “下一页” 和 “最后一页” 图标依然是可以点击的,即没有灰显)。此类缺陷即使对于经验丰富、心思缜密的测试人员,在人工测试时也是很可能发现不了的,并且在自动化测试过程中也很难进行断言。

即使存在上述问题,测试脚本中是否有充分的断言,依然是评判自动化测试有效性的一个重要指标。但实施过自动化测试的人应该都会有这样的体会:“大部分断言在大部分情况下只是佐证软件是运行正常的”。

当然,所有人都应该是非常期待看到这样的结果,毕竟谁也不希望每次回归测试时都是用例大面积不通过。只是辛辛苦苦写这些断言语句的测试人员心里未免有些 “小遗憾”。

本系列上篇文章中谈到 “很多人一提到自动化测试脚本,马上就想到需要提供录制工具”,但如果换个角度思考,很可能就是 “柳暗花明又一村”。

在这里,我们同样换个角度思考,假设我们的自动化测试主要目标是为了证明软件运行正常,那么我们会怎么做?

笔者这边的一个经验就是 “按照完整的业务流程来组织测试用例,只对少量、必要的关键点进行断言”。以 “租户对虚拟化资源的申请使用” 为例,来具体看看测试用例的组织方式:

  1. 新租户注册;
  2. 管理员登录系统,对注册租户进行审批,然后退出系统;
  3. 审批后的租户登录系统;
  4. 租户申请所需要的虚拟化资源(比如,40G 硬盘、2 核 CPU、2G 内存),然后退出系统;
  5. 管理员登录系统,对租户申请的资源进行审批,然后退出系统;
  6. 租户登录系统,在已申请资源的基础上创建安装指定操作系统的虚拟机;
  7. 断言虚拟机是否创建成功;
  8. 租户退出系统;
  9. 管理员登录系统,删除租户;
  10. 断言租户之前申请的资源是否被完全释放;
  11. 租户再次登录系统,断言是否无法登录;

上述测试用例就是按照完整的业务流程进行组织,并且只对少量关键点(7、10、11)进行断言,如果整个用例可以运行通过,就能证明这个业务是没有问题的。

另外还有一个值得考虑的现象,就是相对于自动化测试而言,一个优秀的测试人员在人工测试时是如何判断功能正确与否的呢?他不会死板的只盯着某几个输入域的值,他一定还会同时关注页面上所有数据的正确性、会更加关注业务流程是否正确、会更敏锐的发现页面样式或 UI 逻辑类的缺陷。

为了兼顾 “证明软件正常运行” 和 “人性化的识别软件缺陷”,一个优秀的测试工具应该考虑提供以下多种断言机制。

控件级细粒度断言

即前面提到的最常见的断言方式。在测试过程中,可以在任何位置增加断言脚本,来判断页面指定控件是否存在、控件显示值是否为预期结果等。通常建议只对关键校验点进行断言。

页面级粗粒度断言

通过对比前(之前测试通过)后(后续持续发布)版本在测试用例路径和输入参数相同的情 况下,整个页面内容(包括截图和数据)是否严格相同来做粗粒度断言。

通过页面截图进行断言有两个实现要点:首先要选择一个合适的截图方案(笔者推荐采用 Selenium WebDriver 提供的 TakesScreenshot 接口);其次需要提供图片对比工具,以便测试人员可以一眼看出两个版本页面截图的差异。

下面是笔者在测试框架中实现的截图自动化对比功能的实际效果。下图中左侧部分是 “实际结果截图”、右侧是 “预期结果截图”、中间部分是差异对比,测试人员一眼便可看出其中的 Bug:“表格行选中的翻页缓存(在当前页选中几条记录,翻到下一页再翻回本页,需要保持之前的行选中状态)功能丢失了”。

通过页面数据进行断言的实现方式相对简单一些,首先要提取页面上所有的数据(或文本),接着进行格式化,然后再自动化对比。 “页面级粗粒度断言” 的特点及应用场景如下:

  1. 无需编写任何断言语句;
  2. 需要能够提供可用于自动对比的历史正确版本,特别适用于可以持续构建的项目;
  3. 能判断出 UI 样式和 UI 逻辑类的错误;
  4. 由于对比绝对精准,导致可能存在误判,因此需要人工对差异图片进行排查;【注】由于很多 Web 页面都有渐入渐出、点击时按钮变色等很炫的效果,所以在两次截图的瞬间可能页面的动态样式是不一样的,这就是所谓的 “误判”。笔者对于一个 “动态样式” 适中的项目采用这种断言方式,统计结果表明误判率在 20% 左右。
  5. 鉴于回归测试的时候,通常大部分用例应该是可以通过的,所以 “页面级粗粒度断言” 的投入产出比非常占优势!

基于业务逻辑断言

在测试设计时把有依赖关系的用例一起执行,如果某个步骤出现问题,即便不设置任何断言语句,在当前步骤或后续步骤的测试用例也会执行失败。下面以 “增加、查询、修改、删除” 这个最典型的流程来说明(如下图所示)。

假定在 “增加” 环节出现问题,那么我们的测试用例执行情况可能出现如下几种结果:

  1. 如果在 “增加记录 A” 的用例中包含对是否增加成功的断言,那么测试用例从 “增加记录 A” 开始出错;
  2. 如果在 “增加记录 A” 中不包含断言,而是在 “查询 A” 的用例中包含是否有查询结果的断言,那么测试用例会从 “查询 A” 开始出错;
  3. 如果在 “查询 A” 中也不包含断言,那么测试用例会从 “修改查询结果” 开始出错。

所谓 “基于业务逻辑断言”,就是指上述第三种情况,其特点及应用场景如下:

  1. 无需编写任何断言语句,但测试设计要考虑业务逻辑顺序;
  2. 与 “页面级粗粒度断言” 相比,不需要提供可用于对比的历史正确版本,通常适用于项目刚开发或样式做整体调整等情况;
  3. 断言错误的位置不精准,可能延后;
  4. 执行过程每一步都做截图备份(通过 Selenium WebDriver 可以很方便的实现),可以非常有效的辅助定位准确的出错原因;
  5. 鉴于回归测试的时候,通常大部分用例应该是可以通过的,所以 “基于业务逻辑断言” 的投入产出比非常占优势!

自定义扩展断言

在人工测试时经常有些操作结果的正确与否在当前页面无法做出判断,需要到其它页面甚至系统外部(比如,数据库、输出日志)获取信息来做出判断。以最常见的 “基于数据库进行断言” 为例,测试工具需要支持把断言时用到 “预期结果” 和 “实际结果” 配置为对应的 SQL 语句。

以上介绍了从测试工具的角度可以提供的多种断言机制,在自动化测试过程中应该根据项目实际情况,考虑采用上述多种断言的组合,以弥补控件级细粒度断言的不足。

本系列文章至此,已经分享了如何降低测试脚本的编写、维护成本,如何在不失测试有效性的前提下减少断言成本。改善上述两大问题之后,自动化测试基本上就可以比较顺利的开展了。接下来如何让自动化测试的价值最大化呢?答案就是频繁的执行测试脚本。因此下一步要做的就是持续集成(或者称为每日构建)。


↙↙↙阅读原文可查看相关链接,并与作者交流