写点什么

敏捷自动化测试(3)——让断言不再成为自动化测试的负担

  • 2013-05-17
  • 本文字数:3142 字

    阅读完需:约 10 分钟

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

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

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

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

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

  • 难以对于 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:“表格行选中的翻页缓存(在当前页选中几条记录,翻到下一页再翻回本页,需要保持之前的行选中状态)功能丢失了”。

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

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

三、 基于业务逻辑断言

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

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

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

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

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

四、 自定义扩展断言

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

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

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

作者简介

殷坤,东软集团资深测试经理、技术讲师,10 年软件研发、实施、测试及项目管理工作经验。 目前专注于敏捷项目管理及质量控制、过程改善、自动化测试、持续集成、用户体验提升等方面。

2013-05-17 03:535792

评论

发布
暂无评论
发现更多内容

模块八作业

库尔斯

#架构实战营

flutter系列之:flutter中常用的container layout详解

程序那些事

flutter 程序那些事 6月月更

leetcode 257. Binary Tree Paths 二叉树的所有路径(简单)

okokabcd

LeetCode 搜索 数据结构与算法

消息队列入门MQ

卢卡多多

MQ 消息队列 6月月更

基于华为云图像识别标签实战

乌龟哥哥

6月月更

数据库每日一题---第9天:销售员

知心宝贝

数据库 算法 前端 后端 6月月更

LabVIEW控制Arduino实现超声波测距(进阶篇—5)

不脱发的程序猿

单片机 LabVIEW Arduino VISA 超声波测距

【Python技能树共建】lxml 模块

梦想橡皮擦

Python 6月月更

为什么需要微服务

阿泽🧸

微服务 6月月更

LabVIEW Arduino电子称重系统(项目篇—1)

不脱发的程序猿

单片机 LabVIEW VISA ​Arduino Uno 电子称重系统

【愚公系列】2022年06月 面向对象设计原则(六)-合成复用原则

愚公搬代码

6月月更

动态规划之0-1背包问题(详解+分析+原码)

未见花闻

6月月更

一文读懂Logstash原理

恒山其若陋兮

6月月更

消息队列存储消息数据的 MySQL表

Dean.Zhang

预解析与作用域

Jason199

js 全局作用域 作用域 6月月更

WWDC22 开发者需要关注的重点内容

37手游iOS技术运营团队

iOS16 WWDC22 Xcode14 iPadOS16 macOS10.16

什么是Vue3的组合式 API?

源字节1号

软件开发 小程序开发

BottomSheetDialog 使用详解,设置圆角、固定高度、默认全屏等

yechaoa

android dialog 6月月更 material design

【Spring 学习笔记(十)】Spring 使用注解整合 Mybatis

倔强的牛角

Java spring Java EE 6月月更

使用 select 切换协程

宇宙之一粟

golang 6月月更

直播预告|FeatureStore Meetup V3 重磅来袭!

星策开源社区

机器学习 开源 DevOps 特征平台 MLOps

ConcurrentHashMap 源码分析-put方法

zarmnosaj

6月月更

思科私有动态路由协议:EIGRP

wljslmz

动态路由 6月月更 路由协议 EIGRP

5分钟了解攻防演练中的红蓝紫

穿过生命散发芬芳

6月月更 攻防演练

vue自定义指令

小恺

6月月更

Java—并发容器

武师叔

6月月更

Flutter doctor 显示xcode没有安装的解决办法

坚果

6月月更

LabVIEW控制Arduino实现红外测距(进阶篇—6)

不脱发的程序猿

单片机 LabVIEW VISA Arduino Uno 红外测距

向线程池提交任务

急需上岸的小谢

6月月更

volatile的解构

卢卡多多

volatile 6月月更

RF中使用reuqests的两种方式

红毛丹

Python 6月月更

敏捷自动化测试(3)——让断言不再成为自动化测试的负担_DevOps & 平台工程_殷坤_InfoQ精选文章