add by zhj: 持续集成案例的关键是“自动化测试”,而无论从技术还是从管理的角度,其难点也是“自动化测试”

​​

本文不会介绍持续集成的概念、理论以及相关工具的用法,而是基于实际的项目案例,分享如何利用自动化测试保障持续集成的有效性,同时也借助持续集成提升自动化测试用例的价值。

在本系列的前几篇文章中,首先分析了测试不够敏捷的原因​,然后从“降低测试脚本维护成本​”和“优化断言机制”两方面分享了Web自动化测试的改善实践。

前面几篇文章其实都在讲“如何成功实施Web自动化测试”,本文将要涉及一个很敏感,但不应该回避的话题“自动化测试的意义到底有多大?”。


做过自动化测试的同仁都应该对“自动化测试用例能发现多少缺陷”这话题不陌生,业界也有很多支持“自动化测试用例主要不是用来发现缺陷,而是提高回归测试效率”这个观点的文章。即便这样,“发现缺陷”也像是自动化测试人员“肉中的一根刺”,很多时候大家不愿意去触碰它(不碰就不痛)。这样时间久了,很可能会让自动化测试人员丧失发现缺陷的斗志。笔者在这里就尝试拨动一下这根“刺”,希望可以再次引发大家的思考。

“自动化测试主要不是用来发现缺陷”这一观点的主要依据是“自动化测试是严格按照已有用例进行的自动回归测试”。说白了就是“它每次做的事儿相同的”,所以不能像手工测试那样依靠人的主观能动性来发现新的缺陷。

“它每次做的事儿相同的”,这一点我们改变不了。


但我们能做的是在不同的场景中做“相同的事儿”!从而增加发现缺陷的几率,降低软件释放后风险。

下面就通过实际案例分享笔者在提升自动化测试价值方面的经验:“在持续集成中对每日构建的版本进行回归测试”,并对一些里程碑版本进行“在各种环境组合下(应用服务器、数据库、浏览器、操作系统)的兼容性测试”和“7*24小时的稳定性测试”。

对每日构建版本的回归测试

本案例中的产品是面向云计算领域的通用云环境管理软件,在云数据中心构建及运维过程中提供全方位、多层次的管理能力,基于云环境实现应用的快速部署及其资源的弹性供应,通过简化管理极大地降低成本、提高效益。

产品的逻辑架构、主要技术路线及对应的自动化测试方案如下图所示:


该产品大致可以分为三层:


  • 最底层负责与各类虚拟化资源或物理资源的交互,比如,创建虚拟机、获取CPU利用率;
  • 中间层负责对底层返回的数据进行持久化及业务处理,并向外提供大量REST接口;
  • 最顶层通过多个应用门户向不同类型的用户提供体验一致的交互界面,它本身没有太多业务逻辑和持久化操作,主要靠调用中间层的REST接口来实现。

持续集成方案选择的CI工具是Jenkins,具体步骤如下图:


对每个步骤的要点简述如下:


  1. 更新编译代码
    项目采用分布式开发,需要从不同的配置管理库中更新各个模块的功能代码和自动化测试用例。
  2. 代码质量检查
    项目要求开发人员使用Findbugs和PMD对自己的代码进行质量检查并修正相关问题。同样也在持续集成过程中通过Sonar(集成Findbugs和PMD)使用相同的策略进行代码检查,以确保该要求的执行效果。
  3. 更新数据库
    在更新功能代码和测试脚本之后,自动化测试还是可能出现大面积无法通过的情况。其中一个很常见的原因就是“当天开发库中的数据库结构发生了变化”,而持续集成所使用的数据库并没有更新。
    所以我们执行自动化测试用例之前增加一个“检查开发库和持续集成库的表结构是否一致,如果不一致就做增量同步”的任务。
  4. 执行单元测试
    通过单元测试确保系统与虚拟化资源或物理资源的交互是没问题的。如果这个环节出现严重问题,后面的持续集成任务就没必要执行了。
  5. 部署后台服务
    单元测试通过之后,把后台服务(即,上面说的中间层)发布到目标服务器并启动服务。
  6. 执行REST接口测试
    基于上面发布的后台服务,对其提供的大量REST接口进行回归测试。如果这个环节出现严重问题,就没有必要再部署前台应用并进行后续测试了。
  7. 部署前台应用
    REST接口测试通过之后,才把各个前台门户应用发布到目标服务器并启动服务。
  8. 执行Web UI测试
    基于上面发布的前台应用,执行各自Web UI层面的自动化测试用例(采用本系列前面几篇文章中介绍的方案)。
  9. 发布构建结果
    通报每日构建结果(如下图所示),测试用例按照模块进行分类,对不通过的用例进行分析然后提交相关缺陷。


上述持续集成案例的关键是“自动化测试”,而无论从技术还是从管理的角度,其难点也是“自动化测试”。

从技术角度来说,在上面三类自动化测试中最困难的是UI层面的自动化测试。笔者在本系列前面几篇文章中主要分享的就是这方面的改善实践。

从管理角度来说,要对自动化测试相关数据(比如,用例通过率、用例增长率、代码覆盖率等)实施公开、准确的度量,如下图所示。


度量的最终目标不是为了考核,而是为了改善。

从度量结果中团队能看出问题,才能有的放矢的改善;

从度量结果中团队能看出进步,才能得到激励和信心。



众所周知,没有自动化测试的持续集成是“伪”持续集成。但笔者了解的很多做持续集成的项目都存在着“自动化测试用例很不充分”的问题。

上述持续集成案例中是如何做到充分自动化测试的呢?笔者认为有如下几个要点,希望可以引发大家的思考:


  1. 测试团队负责产品的持续集成;.
  2. 先推行自动化测试后实施持续集成;
  3. 把自动化测试用例通过率和增长率作为迭代的关键度量指标;



兼容性测试

现在软件需要兼容的环境越来越多,包括操作系统、应用服务器、数据库、浏览器,像上面案例中的产品还要兼容主流虚拟化服务(比如,VMware 、XenServer、KVM)的各种版本。如果全靠人工测试来保证兼容性,是不太现实的事情。

兼容性测试有个特点,就是如果不兼容,往往在一些主要流程上就能明确的体现出来,一般不用深入到每个业务细节,也不用靠人来主观分析。因此也非常适合通过自动化测试来完成。

下面分享一个笔者在撰文的前一天刚刚遇到的实际案例(如下图所示)。


这个一个最基本的用户维护界面,里面包括必填信息和可选信息(比如,生日)。在一次自动化测试中,Web UI层面的“用户信息修改”用例出现了如下异常:

Caused by: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect datetime value: '' for column 'ext_date' at row 1

这个功能后台业务接口是有单元测试用例对应的,并且也做了一些边界值测试(比如,“生日”属性为空),但遗漏了另外一个边界条件(空字符串),而恰恰如果界面不选择“生日”,传到后台的就是空字符串。Web UI层面最基本的测试用例恰恰弥补了这个缺憾。


有些人可能会质疑:如果界面不选择“生日”,传到后台的也是空(null),那么这个Web UI测试用例不也一样发现不了这个Bug嘛。

确实如此,但换个角度想一下,如果这样的话,这个“Bug”即使遗漏出去,也永远不会被用户发现。

这正体现了Web UI层面自动化测试的意义——比其它层面的自动化测试更代表用户!



写到这里,可能会有敏锐且尖锐的读者继续提出质疑:“这么表面的缺陷在手工测试阶段一定会发现的,怎么会轮到通过Web UI自动化回归测试来发现呢?”

我们来回顾一下上面的异常信息“Caused by: com.mysql.jdbc.MysqlDataTruncation…”。是的,这个缺陷只有在使用MySQL数据库时才出现,而日常开发和手工测试使用的都是Oracle数据库。

我们把在各种组合环境下的兼容性测试交给自动化用例来完成。因此,如果有兼容性方面的Bug,也是“得来全不费工夫”!

稳定性测试

稳定性测试可以分为“服务端稳定性测试”和“客户端稳定性测试”。其中服务端(比如,应服务器、数据库等)的稳定性测试是最常见的,笔者这里不做赘述。

RIA(Rich Internet Applications)技术的广泛应用为Web用户提供越来越赞的使用体验。与此同时,也比传统应用占用更多的客户端(浏览器)资源。所以对此类应用的客户端稳定性测试也是非常关键的。

验证客户端的稳定性需要两个条件:长时间的不间断操作、监控浏览器资源占用。

我们通过对Web UI自动化测试用例的循环执行可以模拟长时间的不间断操作。另外,在自动执行的同时,自动获取并记录浏览器资源占用,就可以达到验证客户端稳定性的目的。

如果系统前端代码出现内存泄露(比如,弹出页面关闭后未销毁生成的DOM对象),Web UI自动化用例长时间运行后生成的浏览器内存占用报告就会如下图所示:


而正常应该是整体呈水平趋势的锯齿状图形。如果出现上述情况,其表现出来的现象是用户感觉操作响应越来越慢,严重的情况下会导致浏览器宕掉。

至此,本系列文章就结束了。下面用三句短话总结一下本系列的主要内容:


  • Web自动化测试困难的根本原因是什么;
  • 如何才能更容易的成功实施Web自动化测试;
  • 要么不断提升、持续证明自动化测试的价值,要么就变成鸡肋!

最后分享笔者这几年在实施自动化测试和持续集成工作中的一些心得体会:


  • 在设计某个功能“自动化测试应该怎么实现”之前,一定要先全面、仔细的分析“手工测试时是怎么做的”;
  • 当提到自动化测试的“测试设计”时,不光要考虑“测试用例设计”,一定还要考虑“自动化测试方案或框架的设计”
  • 敢于面对各种质疑和挑战,并用持续的改善作为回应;
  • 对于开发团队来说“不改善,尤可活”,对自动化测试来说“不改善,就等死”;
  • 不断发掘自动化测试对各个团队的附加价值,只有这样才能得到来自四面八方的支持;
  • 自动化测试的目的是节省成本,所以如果发现某个项目、模块或功能在进行自动化测试时的投入产出比还不如人工测试,就应该果断暂停;
  • 当有人用“自动化测试的返工成本”来刻意刁难测试团队时,不妨请他考虑一下研发阶段的返工吧;
  • 对测试用例失败的原因进行归类(比如,缺陷、环境错误、用例未更新等),并据此生成测试报告,非常有助于提高测试结果分析的效率;
  • 在持续集成过程中,最初觉得技术是个坎儿,迈过之后发现管理是个更大的坎儿。要想持续集成获得成功必须让研发、测试、实施等各个团队都认识到它对自己的价值,然后大家才会主动的、同心协力将此事做好;
  • 再忙也必须每日修正完持续集成测试发现的缺陷,唯有此持续集成发现的缺陷比才会越来越少。当每日构建都能成功的时候,团队信心和士气会得到很大的提振;
  • 每次集成后测试用例全部都通过和基本都不通过都是不正常的现象,“全部都通过”往往代表测试用例覆盖率不够或缺乏有效断言,“基本都不通过”则可能因为研发提交代码质量太差或持续集成环境有问题;
  • 持续集成的过程很不易,涉及技术改进、资源投入、团队协作、文化养成等各方面,但做成之后觉得每一分投入都非常值得;
  • 水滴石穿、贵在坚持!

作者简介

殷坤,东软集团资深测试经理、技术讲师,10年软件研发、实施、测试及项目管理工作经验。

目前专注于敏捷项目管理及质量控制、过程改善、自动化测试、持续集成、用户体验提升等方面。


感谢侯伯薇对本文的审校。