起因

我的同事肖然在 《ThoughtWorks的敏捷开发》一文中介绍了ThoughtWorks敏捷开发的全貌,并在其中简单介绍了ThoughtWorks是怎么做质量内建和敏捷测试的。我作为一名加入ThoughtWorks已经7年的QA,想更为详细的介绍一下这些内容,希望能帮助业界中仍对于敏捷测试有疑虑和困惑的团队建立起自己的敏捷测试体系和实践,从而帮助团队更好的实施敏捷软件开发。

在目前的软件开发领域,敏捷依然没有被广为采用,很多人诟病其:

  • 开发速度其实并不比传统的开发方式快
  • 软件质量得不到保证
  • 无法应用于大规模软件开发
  • 文档少导致开发出来的软件难以维护
  • ……

其实大多都是在不了解敏捷开发中质量内建与敏捷测试的情况下得出来的。如果只是阅读《敏捷宣言》,是很难以理解其中关于质量内建和敏捷测试的相关内容。所以通过长期的项目实践,我们对质量内建以及敏捷测试总结出了一套自己的理论和实践体系。

测试在流行敏捷开发方法中的缺位

业界有很多所谓敏捷开发流程,比如Scrum,Kanban等,但是其中测试相关的内容相对较少,并且不够系统化和细节化,所以业界就出现了很多测试人员,他们总结了测试人员应该在敏捷开发中如何进行测试工作。由于很多测试人员也是公司或者团队在Scrum和Kanban的转型中接触和学习到敏捷,然后通过有限的资料以及自悟在团队中进行敏捷测试,又在一知半解下又去宣传敏捷测试或者去抵制敏捷测试,导致敏捷测试甚至敏捷本身在国内乱象丛生。

首先敏捷测试一定是敏捷开发方法的一部分,所以敏捷开发方法论里面应该需要包括敏捷测试的相关内容,但是现在业界中所谓的一些标准的敏捷开发流程里面却很少包含系统化的测试实践。由于敏捷测试实践或者说敏捷实践的核心就是缩短反馈周期,逐步优化整个系统。并且因为每个团队的情况都是有差距的,所以通过同一种标准的方式去要求所有不同的团队,则会产生很多负面的效果。

现在业界已经有不少通用的敏捷测试实践,以及一些在特定条件下面的经典流程(后面会介绍一个经典的敏捷测试管理流程)。其次对于大规模敏捷开发中的敏捷测试来讲,其核心还是在开发团队里面合理使用各种敏捷测试实践,缩短测试反馈周期。

因此不管敏捷开发还是敏捷测试里面的敏捷都没有一个所谓统一的最终敏捷,应该是需要越来越敏捷的状态才是最好,然后最终达到自己项目的一个稳定敏捷状态就可以。

敏捷测试的原则

ThoughtWorks没有Tester这个职位,而是叫做QA。这里的QA不是”Quality Assurance”,而是”Quality Analyst”——质量分析师。其主要工作是在承担项目部分权责的情况下,负责各种质量相关的工作,通过各种实践让团队中所有人都会对质量负责,并做一部分质量相关的工作。

QA每天都可能需要根据不同的情况而相应改变自己的工作内容,虽然每天主要的工作内容仍然是测试相关的各种工作,但是并不一定需要自己独立完成它们,其中还包括把所有团队成员组织起来,一起协作完成这些工作。并通过各种实践,让每个成员都能承担最适合自己的质量相关的工作。QA需要了解并熟悉所有质量相关的活动和工作,并根据项目的情况将它们合理的组合起来使用。我们还总结出了一些敏捷测试的原则:

  1. 我们的目标在于和团队一起尽快地交付高质量软件。
  2. 测试人员尽早参与软件早期阶段,与所有团队角色合作,通过实例化需求,确保对业务价值理解的一致性。
  3. 测试人员关注生产环境状态,收集数据,指导和优化前期的分析、开发和测试。
  4. 测试人员和开发人员同处一个产品项目团队,而不是独立的测试团队或部门。
  5. 测试人员负责探索性测试,和开发人员结对,设计、实现和维护自动化测试。
  6. 自动化测试在流水线中持续精准执行,快速发现每次代码提交对于已有功能的影响
  7. 测试数据对于自动化测试是充分的,并能按需获得。
  8. 测试活文档化,和代码一起,作为知识资产进行版本化管理。
  9. 自动化测试需要有效的分层。
  10. 预防缺陷,而不是关注缺陷的数量。

这些原则展示出了敏捷测试的特点,指导我们更好的实施了敏捷测试,使得我们不仅仅关注测试本身,完成相关的测试工作,而且还要真正的在测试工作中关注并实施敏捷,并且通过各种敏捷实践来促使全员负责质量的目标,最终在有限的时间内尽最大可能正确的交付客户价值。

敏捷测试实践与管理体系

在过去的20多年中,我们的QA通过大量的项目经验,总结出了许多敏捷测试实践,比如测试前移、每日结对检查以及线上测试等等。我将它们分为三个部分,分别是迭代开发中、故事卡开发过程中和产品环境中的敏捷测试实践,分别从三个不同的维度总结了我们的各种敏捷实践,从而帮助大家更为系统化的了解它们。

迭代开发中的敏捷测试实践

在真实的项目中,如何有效的将各种敏捷实践组织起来,并在不同的团队中使用,是敏捷测试管理最大的一个挑战。由于每个团队的情况都不一样,比如产品规模,业务目标,人员能力等,导致敏捷测试流程和管理体系都会有所区别。虽然有所区别,但是敏捷测试管理还是围绕着敏捷的核心价值进行管理,并且有自己特有的流程体系和度量体系。

通过多年的交付和咨询经验,我们的QA们总结了不少敏捷管理的实践和经验,并形成了一套经典的测试流程,适用于业务复杂的企业级软件系统的开发。其完全是符合经典敏捷开发流程的,但是在真正项目实践时,需要根据项目自身的特点和资源优先级来选择其中适合自己的实践,从而尽可能的满足当前项目对于软件质量和测试的需求。

理论上的最佳实践是每个迭代里面都能完成当前迭代计划的卡的开发和测试工作,并且完成发布到线上的工作。下图为理想情况下的敏捷测试生命周期最佳实践图。

敏捷测试之迭代生命周期(最佳实践模型)

但是在实际的开发工作中很难做到理想的最佳实践模型,所以我结合自己的工作经验总结了一个典型的实践模型(见下图)。在整个开发流程中,将不同的测试方法和测试实践按照测试策略和测试计划加入到整个迭代开发中,从而在每个迭代中实施它们。

敏捷测试之迭代生命周期(典型实践模型)

在整个生命周期中一定要使用持续集成以及持续交付中的各种实践,并且周期性的快速交付一些功能已经逐步被大家所认可。其中能帮助快速交付的一个最重要的步骤就是回归测试,所以应该尽可能自动化回归测试用例,加速交付过程。QA需要思维敏捷并且富有创造力,而大量周而复始的手动回归测试会阻止QA锻炼思维和创造力,其次长时间大规模的手动也是很容易出错的。

图中有性能测试等非功能测试。对于一些质量要求很高的项目,特别是对于性能,安全以及稳定性很高的项目,除了功能测试以外,还需要做大量的非功能测试,比如压力测试,耐久性测试,负载测试,灾备测试,安全测试以及各种异常测试等。这个时候就需要QA拥有相关的知识来负责这些测试,可以是自己做,也可以是教其他人做,比如团队的开发人员等,或者由自己把关并外包给其它公司做。

在项目开始阶段,开发人员开始开发工作前,QA还需要完成以下实践:

测试分析

由于测试前移,测试分析所关注的实践要关注更多的东西,它包括风险分析、测试设计等。风险分析需要尽可能的指出业务或者技术层面上问题,它们会在什么时候、在什么地方、对产品的利益相关者产生多大的影响等。测试设计则需要指出如何在有限的时间和资源的情况下如何高效的覆盖高风险的功能等。QA必须在每个项目中都做测试分析,并且在项目的不同的阶段都需要做。比如和业务分析一起结对写验收测试条件的时候、设计回归测试套件的时候、做探索性测试的时候、开发和维护自动化测试的时候,以及当要忽略回归测试套件中某些测试用例的时候。

测试策略

QA需要经常和团队的其他成员合作来完成测试策略,比如开发人员、项目经理等。由于一个大型软件项目需要开发大量的自动化测试,并且不少自动化测试都需要开发人员来完成,所以需要有一个测试策略来指导整个团队成员来完成各种类型的测试,比如单元测试、功能测试、服务契约测试、界面测试等等。

故事卡开发过程中的敏捷测试实践

其次在每个不同的迭代周期中,敏捷测试实践的主要工作就是围绕故事卡来进行。对于每个单独的故事卡,我们也有一套自己的敏捷测试故事环。需要注意的是,这个敏捷测试故事环和这些敏捷测试实践只是一个经典模型,在真实的不同项目的实践中会有所改变。

故事卡生命周期(经典模型)

上面是敏捷开发故事环,在环中不同的阶段需要加入我们定义的经典敏捷测试实践,就形成了敏捷测试故事环。其中实践包括:

故事启动

在传统瀑布开发模式中,测试人员一般是不参与故事启动相关工作,但是在敏捷开发流程中,QA需要从这里就开始介入,其经典实践包括:

  • 需求澄清
  • 业务场景和验收测试(AC)的确认

这个实践也属于测试前移。这两个实践的核心是需要QA和业务分析人员以及开发配合,一起来澄清所有不清楚和有疑问的需求,并确认所有的验收条件即验收测试用例。如果QA发现业务需求分析本身有问题,或者验收条件不合理、不可测等,那么QA就需要挑战这些问题和不合理,尽量保证开发拿到的故事卡是业务清晰,验收条件合理并可测。通过这些实践可以实现测试前移和ATDD,尽量在开发之前发现缺陷,从而预防缺陷,并保证三方人员对于需求的理解都是一致的。这个活动也称为Kick Off。

故事计划

故事启动并澄清需求后,就是故事计划了。其实很多团队是没有故事计划的,或者故事计划是在迭代开始前一次性做一次。不过我们还是建议在每个故事开发前做一个简短的计划工作,用于计划这个故事卡。在其中QA需要计划测试工作,其经典实践包括:

  • 测试工作估算
  • 制定测试计划

这个测试计划和工作估算是针对这个故事卡的,其中包括我需要对这张卡做哪些测试,测试数据和测试环境的计划与准备,测试工作大概需要多少个点等。但是估算并不是承诺,只是让大家了解测试工作内容的复杂度以及困难度。对于困难的测试点,则可以计划让开发人员帮助一起做。

故事开发

如果有故事计划,那么完成计划之后开始开发工作,如果没有就在故事启动后直接开始。在开发过程中,QA需要尽可能的在开发完毕之前发现产生的缺陷,从而实现缺陷的快速反馈,其经典实践包括:

  • QA和开发结对实现自动化测试
  • QA和开发或者业务分析结对做每日内部演示和反馈(Desk Check 或者 Shoulder Check)
  • 及时和团队沟通发现的问题和缺陷

这三个经典的实践可以防止缺陷流动到测试阶段,减少缺陷的反馈周期,减少返工的成本,从而降低软件开发周期,提高单位时间内的软件质量。

一个团队中不同角色的人会关注不同的风险和问题。比如QA需要详细的,精准的将缺陷告知开发人员;但是对于PM,QA需要帮助其了解项目整体上的风险,帮助其管理项目进度和发布计划。所以记录缺陷,并且对于严重缺陷或者风险需要告知整个团队或者管理层是QA的一项重要工作。

对于那些自动化测试成本很高的项目,应该首先至少做一遍手动测试后,然后做完之后再来评估哪些需要做自动化,哪些不需要。

故事验收

通过前面加入了敏捷实践而开发出来的功能,其验收测试的用例应该大部分甚至全部通过。但是为了防止漏网之鱼以及开发人员最后提交的代码修改出现side effect,我们仍然在开发完成之后定义了一个“故事验收”阶段,用于整体验证功能的所有验收条件等,其经典实践包括:

  • QA和业务分析结对进行快速验收测试,提供快速反馈

通过这个环节,可以尽可能的保障验收条件不会存在缺陷,从而减少缺陷发现和修复的周期。但是如果业务没有时间,也可以由QA一人或者QA和开发人员结对完成。

验收测试可以是手动测试,也可以是自动化测试。但是大部分实际情况中,都是先做手动测试,再通过手动测试的用例再来编写自动化测试。对于实现了ATDD的团队,那么也建议在功能开发完毕后做一遍手动测试,因为自动化测试很多时候可能会遗漏一些验证条件,忽略一些细节。而通过至少做一遍手动测试,可以发现一些通过自动化测试发现不了的东西。比如发现了一个bug,需要添加自动化测试来覆盖它;或者某些自动化测试断言过少;或者某些测试没有实践的意义,或者是重复的,需要删除等。

故事测试

通过故事验收以后,理论上验收条件应该大部分或者全部满足了,所以不应该存在明显的缺陷了。这个时候应该做更多的测试,比如探索性测试,安全测试等,从而发现验收条件以外的缺陷。其经典实践包括:

  • 执行探索性测试,安全测试等
  • 强调会阻碍故事发布的风险因素
  • 为测试发现的严重缺陷添加自动化测试
  • 执行自动化验收测试,可以是回归测试

通过这个环节可以尽最大可能发现所有问题,并在最后给客户演示之前评估完所有的风险,并尽最大可能防止风险会影响到客户。

系统测试和客户演示

如果故事功能属于一个完整业务流程中的一个节点功能,那么这种情况下就需要进行业务层面上的端到端测试。当端到端测试成功之后,就可以进行功能的最终客户验收演示,从而最终完成功能故事卡的开发。其经典实践包括:

  • 执行业务层面上端到端的系统测试
  • 和团队及客户就功能特性的质量和稳定性进行沟通
  • 给客户验收功能和特性

如果客户验收成功,那么这个功能就可以准备上线了。但是如果验收失败,就需要进行分析,为什么失败?确认是第一步“故事启动”里面的验收条件有错误或者遗漏,还是功能本身就分析和设计错误,满足不了客户的需求。然后通过“5 Whys”或者“Retro”等会议找到为什么验收失败的原因,并且制定下一步改进的方案。理论上,通过前面这些步骤之后再验收失败的可能性很小,除非业务分析人员本身由于能力等原因就从最开始就分析错了,并且通过和开发人员、QA等的结对也没有发现。虽然仍然没有办法避免验收演示失败这种小概念事件,但是一旦发生,由于敏捷中的持续改进,我们可以通过持续改进并进一步减小其发生的概率。

除了敏捷测试故事环中的常规工作和实践,还需要经常对测试进行维护与重构。一般一个成功的大型软件项目都有大规模的测试用例或者自动化测试,并且项目的成功与否和这些测试用例或者自动化测试的有效性以及健壮性直接相关。但是现实中大规模自动化测试有一个大问题,那就是“易碎性”。而这种“易碎性”最主要是由于环境的改变或者自动化测试代码的改动。对于环境的改变,测试人员应该参与到DevOps建设中,从而建立起一套稳定的测试环境,包括测试数据系统等。而对于自动化测试脚本的改变,很多时候是由于新加功能而需要修改测试系统通用代码,从而导致的副作用。所以对于自动化测试代码也需要像对待产品代码一样,进行重构和维护。

产品环境中的敏捷测试实践

当一个发布版本开发(包括测试)完成以后,就需要进行部署和发布。而我们的QA也需要参与发布管理。由于QA参与并且负责了大量质量相关活动,所以对于软件系统的整体质量有较高的认识。所以QA有责任参加发布会议,并且参与决定是否发布的决定。

当产品真正交付到用户手中或者发布上线以后,我们的QA仍然需要在产品环境中做质量相关的工作,称之为产品环境中的QA,或者叫测试后移。这将工作范围扩大到产品环境,增加了更多的反馈来源,跟持续交付结合,可以帮助持续提高产品质量、持续优化业务价值。

产品统计数据分析

产品环境中软件系统在运行过程中会产生大量的数据,如果通过A/B测试还可以获得大量不同特征的数据。而通过分析这些数据,往往可以找到优化和提高软件质量的方案。比如统计一个Web系统在产品环境下所有页面的下载和加载的平均时间、最长时间以及趋势,可以有效的发现一些性能问题;又比如客户端浏览器类型统计,可以帮助优化测试策略,加强对于用户量最多的浏览器的兼容性测试等等。从而通过这种方式有效的持续提高产品的质量。

可调式性日志分析和优化

现代的服务系统越来越复杂,导致调试也越来越困难,特别是线上调试就更为困难。很多线上系统主要是通过日志来进行调试,所以日志的可调式性就非常重要。因为日志的可调式性直接影响到了当产品出现问题之后调试并发现问题原因的速度和时效,如果可调式性好,那么产品环境遇到问题后修复的时间也会相对缩短。因此QA可以通过各种机会,比如定期,或者某次产品遇到产品环境问题后,对于产品环境的日志进行可调式性分析,并协助团队一起对其进行优化。

持续业务功能监控

当前业界对于产品环境的监控主要以服务监控为主,比如服务是不是在线或者下线等,而很少做业务功能级别的监控,比如监控某一个核心业务功能是不是工作正常。而产品环境下的QA需要帮助团队搭建核心业务功能的监控方案,比如提供测试场景和步骤,提供业务成功的验证方案等等。然后当某个业务功能工作不正常的时候,但是系统服务仍在线的情况下,依然可以在最短的时间内获得业务功能的反馈。

除了上面三个主要的实践以外,QA还可以在产品环境下做更多的一些实践来获得质量的快速反馈,从而提高产品系统的质量。所以产品环境下的QA是未来特别值得深入研究的一个话题。

除了以上介绍到的敏捷测试中的实践,其实还有其他一些适合不同团队的敏捷实践,这里就不再赘述了。

总结

通过我们长期的项目实践,思考与洞见,不仅总结出了10条敏捷测试的原则,还有了我们的敏捷测试宣言:

全程的测试介入 over 孤立的测试阶段

团队整体对质量负责 over 测试人员独力把关质量

持续性的精准自动化测试 over 回归式的全量自动化测试

质量内建 over 质量检测

这个敏捷测试宣言基本上体现了我们敏捷测试的核心实践,并且和敏捷宣言一样,尽管右项有其价值,但是我们更重视左项的价值。

在这种敏捷测试的实践体系中,我们的开发测试比通常可以做到2~4 : 1。但是这个不是绝对的,我们有少部分项目可以做到5:1或者更高,因此不同的项目都需要根据自己的实际情况来制定这个比例,比如项目时间、质量需求、人员能力等等。通过我多年的工作中的观察以及总结,我发现开发人员技能越高,愿意并能做越多的测试工作,那么测试开发比就越大。而在开发人员技能等同的情况下,软件系统的业务复杂度越高,开发测试比就越小。

最后,你们做了敏捷测试吗?和我们做的差距大吗?