7.1 回归测试

    至此,我们在第 5 章讲了持续集成(Continuous Integration,CI),在第 6 章讲了持续交付(Continuous Delivery,CD)的相关内容。本章来讲解一下持续测试的相关内容。

    7.1.1 什么是回归测试

    为了使 CI、CD 更为实用,回归测试就变得必不可少。回归测试是以检查退化为目的的测试。虽然在第 5 章接触了自动化测试,但那只是从开发人员视角出发的单元测试。本章将更进一步,来看一下从用户视角出发的回归测试,即集成测试、用户验收测试的相关内容。

    一般来说这类测试和使用系统的用户一样,利用浏览器进行输入或页面迁移,并测试是否得到所期待的结果或页面。因此执行一个个测试用例的时间往往变得很长,如果是长年运维的系统,到所有测试执行结束为止耗费大量时间的情况并不罕见。

    事实上,在笔者所在的公司,为了确认前一天提交的结果是否通过回归测试,往往要耗费数天的时间。为了解决这个问题就需要并行执行测试。

    本章将讲解为了实现针对 Web 服务的回归测试自动化所必需的并行测试的相关工作,以及具有代表性的用户验收测试自动化工具 Selenium 的使用方法和一些小技巧。

    并且,以确保产品质量为主要职责的工程师,往往并不擅长编程。这样的情况下应该如何实现高效的自动化回归测试呢?对于这个问题笔者也将给出自己的答案。

    7.1.2 测试分类的整理

    产品开发中需要根据不同目的实施各种种类的测试,并且其数量之多,往往会将人压得喘不过气来。因此在进入正题之前,首先对测试这一概念进行简单的整理。开发流程中应该如何计划并实施测试,以及什么种类的测试和发现怎样的 bug 有关,了解上述内容是进行测试的第一步。

    测试可以被分为 4 个象限 1 (图 7.1)。这个分类方法将各种测试依据“业务层面看到的”和“技术层面看到的”,以及“以支持团队为目的进行的”和“以评价产品为目的进行的”的不同,用 2 根轴分为 4 个象限,并且在 4 个方块中给出了各类测试的主要手段。

    1 (美)Janet Gregory、Lisa Crispin 著,孙伟峰、崔康译《敏捷软件测试:测试人员与敏捷团队的实践指南》,清华大学出版社,2010 年。

    7.1 回归测试 - 图1

    图 7.1 测试的 4 象限

    下面对各象限的概要进行讲解。

    ●…… 支持团队的技术层面的测试(第 1 象限)

    基於单元测试的测试驱动开发(Test Driven Development,TDD)等开发中的主要测试。主要是和内部品质相关的内容,代码的版本管理系统、集成开发环境(Integrated Development Environment,简称 IDE),以及编译自动化工具等也属于这个范畴。

    ●…… 支持团队的业务层面的测试(第 2 象限)

    与第 1 象限偏技术相对,该象限是更接近于业务的顾客观点的测试。除了功能测试以外,原型、仿真、需求以及画面设计等以推进开发为目的的活动也可以作为一种测试在此进行。

    并且,这里的测试是用负责业务的工作人员能够理解的语言或格式来记述的,这些测试中的大多数都应该、且已经实现了自动化。该领域还包括借助 Fit2 、Selenium、Cucumber3 、Watir4 以及 Canoo WebTest 5 等工具的自动化测试。

    2 http://fit.c2.com/

    3 http://cukes.info/

    4 http://watir.com/

    5 http://webtest.canoo.com/

    ●…… 评价产品的业务层面的测试(第 3 象限)

    从业务的视角出发,为了评价产品而进行的测试。探索测试 6 、可用性测试 7 以及用户验收测试 8 属于这个象限。

    6 一种探索着进行的测试。不是根据事前准备好的测试计划来执行测试用例,而是一边熟悉产品一边对可疑之处进行测试,并根据测试结果随机应变地进行下一步测试。

    7 从用户的视角来确认产品的 UI(用户接口)哪里有问题的测试。

    8 检验完成后的产品是否满足需求规约的测试。

    基本上是以对用户接触的部分进行测试为中心,相对于第 1、第 2 象限侧重于自动化方面,这是只能由人手动实施的测试。

    ●…… 使用技术层面测试的产品评价(第 4 象限)

    性能测试、安全性测试等,基本上不使用技术就难以实施的测试。

    ◆◆◆

    针对开发流程中应该注重哪些目的,或者说可以省略哪一部分,可以对照着测试的 4 个象限来确立测试方针。另外,为了确认正在实施或者即将实施的测试是出于什么目的的等,也可以参考测试的 4 个象限,这样在团队以及组织内容易达成共识。

    7.1.3 回归测试的必要性

    ●…… 退化(degrade)的发生

    由于系统的版本更新,在之前的版本中正常运行的功能变得无法正常运行,或者紧急修正了某个问题,但引发了其他新的问题……想必谁都经历过这种退化的现象吧。

    虽说如此,为了在代码变更时保证质量,既然无法预测系统的何处会发生退化,就必须实施回归测试以确认没有预想外的影响发生。

    并且,如果通过回归测试发现了 bug,为了确认 bug 还需要更进一步实施回归测试。但是这样的测试流程需要较多的时间,因此如果不实现自动化,在实际项目中就很少会被运用。

    ●…… 应该实现自动测试的原因

    那么应该怎么做呢?从修改的代码确定影响范围,再从重要程度等风险的观点出发确定测试范围后实施测试,这可能是一般的作法。但是笔者认为通过实现回归测试的自动化,每次都执行所有的测试用例,能够最有效地保证质量。

    人为判断执行哪些测试用例本身就可能产生失误。根据时间的限制来决定可以执行的测试范围和测试量,最终只要不执行所有的测试用例,还是难免会担心。

    实现测试的自动化还会带来其他的一些好处。正如我们在第 5 章中说明的那样,每次提交后执行测试,如果能够即刻发现问题,那么问题就能被迅速地解决。

    若提交 1 周后才收到当时的修改引发了新的问题这样的报告,有时就需要先回想一番后才能着手。因此实现测试的自动化,频繁地实施测试还能够加快开发速度。

    为了减少退化 bug 要怎么做才好呢?在此之前人们为了减少退化 bug 进行了各类尝试,得到的答案是:通过人工测试来保证质量,从效率以及速度上来说都有其局限性,只有通过自动测试才行。从在此之前的手动测试转变为重视自动测试,发生退化的数量也得以大幅减少(图 7.2、图 7.3)。

    7.1 回归测试 - 图2

    图 7.2 通过自动测试发现的 bug 在所以被发现的 bug 中所占的比例

    7.1 回归测试 - 图3

    图 7.3 退化数量的变化

    当然自动测试的效果根据产品的特性会有所变化,但不难看出,无论是对于提高产品的质量还是顺利推进开发来说,回归测试的自动化都是重要的因素。

    7.1.4 回归测试自动化的目标

    说起实现回归测试的自动化,之前叙述的各个种类的测试中哪些应该实现自动化呢?首先,一般来说是由开发人员实施的单元测试。可是无论单元测试的覆盖率如何提升,仅靠单元测试是无法保证产品的质量的。单元测试作为确保程序的动作和开发人员的意图相一致的测试,即使达到 100% 的覆盖率,还是有如下这些 bug 无法发现。

    • 在程序中的 for 或 while 这样的循环中,不进入循环体或者超过 了最大循环次数等边界值相关的 bug

    • 包含预料之外的数据时的异常处理不充分而导致的 bug

    • 共享内存的操作或数据库的锁处理等,由于进程、线程间共享数据而在特殊的时间点发生的 bug

    • 使用了中间件的某个特定版本(Web 服务器、数据库服务器、邮件服务器等)而产生的 bug

    • 需求自身的问题所造成的 bug

    • 功能未完成而造成的 bug

    多数系统会使用数据库服务器或缓存服务器这样的中间件,或者通过 API 调用其他 Web 服务的资源,很多功能仅有系统自身无法运行,因此就需要在和实际产品相同的环境下进行测试。并且还有可能发生和用户所使用的 OS 及浏览器相关的 bug。因而需要对各种条件下系统的运行要求是否得到满足进行测试。

    所以,不仅仅是单元测试,还需要从最终使用系统的用户视角出发的集成测试。不过值得庆幸的是,这种集成测试的自动化工具正在不断地被开发出来。下面讲解的作为 Web 应用程序测试框架的 Selenium 就是一款著名的测试工具。