与传统测试不同,在敏捷测试中,测试的基准不再是需求规格说明书,而是用户故事。用户故事是在敏捷开发模式中针对需求名称所使用的一个专业术语,强调要从用户的角度出发来识别和获取用户真正的需要和诉求。
传统软件开发方法论的假设是基于“用户认知不会发生变化”且“软件系统设计人员能够正确理解”这两个假设建立的,我们通过详细设计的过程能够得到更好的产品。而现实情况是,越复杂的系统,需要的设计时间越长且设计成本越高。在软件诞生之前,用户或客户要承担巨大的风险,因为在软件开发完成并交付使用之前,所有的成本都是没有回报的投资,如果这一过程中出现了变化,就会产生更大的风险。
此外,用户或客户的想法往往是模糊且易变的,加之软件本身是一个抽象模型,并不像客观的物理实体一样拥有统一的度量标准和解释。例如,一根一米长的钢管,通过长度和材质就可以将其限定为一类物理实体,这些物理实体的范围虽然可能很大,不过不同人的认知很容易统一。但是,“一个登录按钮”这一抽象概念在不同人的理解中有很大差异。
因此,敏捷软件开发的核心思想就是使用较短的时间交付一个有价值的(Valuable)、工作中(Working)的软件,基于已经构建的客观基础进行增量开发。用已投入工作的软件进行沟通,可以减少抽象概念的不一致性。用户或客户通过不断交流对齐理解,从而实现共赢——客户能够有效地传递信息,软件开发团队可以正确地理解信息。所以,敏捷软件开发的过程实际上是通过频繁且有效地持续沟通,缩小期望所得与实际所得的差异,从而获得风险更小且感受更好的投资回报。
以前的开发人员会根据文档而不是用户的直接描述进行理解和开发,这种开发被称为“瞎猜”,因为从用户提出想法到开发人员拿到文档,这一过程已经历了多次传递,信息会失真,用户的期望将与收获的结果不一致。最好的解决方法是开发团队和用户一起进行设计并时时沟通,这样开发人员将直接获得一手用户信息,而不是通过中间人传递。因此,为了时刻把用户——使用软件的人放在软件开发的核心位置,敏捷社区发明了“用户故事”实践,这是用户以其自身需要为出发点提出的一个场景化概念。
用户故事有两个好处。一是人类本身就是用户故事驱动的动物,人类对用户故事的印象远比对结构化知识的理解更加迅速和深刻。例如,“牛顿被一颗苹果砸中,从而提出了万有引力定律”,这是一个用户故事,而“任意两个质点由通过连心线方向上的力相互吸引,该引力大小与它们质量的乘积成正比,与它们距离的平方成反比,与两物体的化学组成和其介质种类无关”,这是万有引力定律的定义,也是一个结构化的知识。为了让这个结构化的知识更方便记忆,人们提出了万有引力定律的公式: F= ( G × M ₁× M ₂)/ R ²。相信苹果砸牛顿的用户故事会比万有引力定律的定义及公式更加吸引人。
二是传统的文档本身就是一种结构化的描述,这种描述缺乏实践序列的因果关系,不能使开发人员产生代入感,也不便于记忆。因此,当开发人员拿到需求时,就会按照其规格,以自己而不是以用户为中心来开发软件。而用户故事是一种话术,它将时刻提醒软件开发团队以用户而不是以自己为中心开发软件。
用户故事的编写遵循一定的格式规范,这点与传统测试大相径庭。传统测试的需求描述多数采用叙述性描述,不仅描述冗长、事无巨细,而且容易无法聚焦客户的真正诉求。相反,在敏捷模式中对需求的描述应采用如下格式。
As ……(作为一名用户/客户)
I want to ……(我想要达到的目标是什么)
so that ……(以及达成目标的原因)
例如:
作为 一名银行用户
我需要 拥有一个账户
以便 我可以存钱、取钱,并且显示当前余额
如果可能,建议测试人员也参与用户故事的梳理和编写,以便能够更加深刻地理解用户真正的需求。如果不具备相关条件,那么至少测试人员需要参与用户故事的讨论和评审。
什么样的用户故事是合格的用户故事呢?答案是遵循INVEST原则。INVEST由6个单词的首字母合并组成,具体说明如下。
一个用户故事应该尽量保持相对独立,尽可能避免用户故事之间相互依赖。用户故事之间的依赖性会为编排计划、确立优先级和估算故事点等增加难度。在通常情况下,可以通过组合用户故事或拆分用户故事的方式减少依赖性。
在实践中,独立性往往是指在一次迭代中,开发团队无论先开始哪个任务,都不需要等待或不会被阻塞,如果出现等待或被阻塞的情况,就证明这个用户故事是有依赖的。注意,此处以一次迭代作为度量依据,也就是说,如果在实现一个用户故事之前,需要在一次迭代内先完成其他用户故事,那么这个用户故事就不是独立的。依赖性可能出现的场景和解决方法分为以下4种。
(1)用户故事粒度太细:这会导致用户故事间的依赖明显。解决方法是合并依赖的用户故事。
(2)依赖用户故事错序:可以把依赖的用户故事先放入此迭代实现,再把其他用户故事放到下一次迭代。
(3)团队成员太多:这可能导致以上2个原因同时存在。可以根据速率(Velocity)重新调整用户故事数量,以此匹配团队规模。
(4)迭代长度太长:如果交付能力已经得到提升,如用户故事交付的数量或速率已提升,那么就可以缩短迭代长度,毕竟,更快地交付客户满足的软件是我们追求的目标。
一个用户故事是可协商的。用户故事的卡片包含对其功能的简短描述。可以通过注释来增加用户故事的细节,但是不能有过多的注释,需要简化成一两句短记录,这样才能提醒团队需要和客户进行讨论。此外,用户提出的想法开发团队不一定能够实现,所以在沟通过程中,开发人员可以尽量避免给出不切实际或有风险的承诺。传统软件开发的一个特点就是“DDD”——Deadline Driven Development(截止时间驱动开发),这一特点本身没有问题,问题是在预算、时间和知识有限的情况下,项目范围不能变,于是团队被迫以加班的方式完成软件开发任务,而用户对软件的期望高于实际所得,最终双方都不满意。
客户往往会希望以更低的成本得到更多的投资回报,因此会在有限的预算下做出超出团队交付能力的估计。然而,质量、时间和范围三者很难同时拥有,常见的情况是保证实现后两点,往往牺牲了质量。但是,牺牲质量就意味着牺牲了价值,因此在时间和质量要求固定的情况下,比较好的方式是更倾向于减少范围。
此外,可协商的另外一个意思是不能有具体的规格和描述,否则,这个用户故事就不能讨论了。用户故事不是新的需求规格,而是引导协商讨论的方式。需要注意的是,可协商的意思不是必须协商,而是可以被协商。如果与客户彼此之间的信任度很高,就不需要逐一协商用户故事,但一定要进行确认。
每个用户故事对客户或最终使用者来说必须是具有价值的,我们需要避免只对开发人员有价值的用户故事,因此,最好的方式是让客户写下这些用户故事,以确保它们对客户来说是真正有价值的。有价值的含义包含以下2点内容。
(1)用户迫切想要解决的问题,这是一个以时间为参数的函数,也就是说,按照客户描述的用户故事在实现后,一定能以时间价值作为其衡量尺度,例如,节约了搜索时间、节约了记忆时间、节约了操作时间、减少了错误频率。此外,货币价值也可以看作一种以时间为尺度的度量,如节约了10万元,相当于减少了公司雇佣1个人10个月所付出的人力成本。
(2)可以根据价值大小和紧急程度进行排序,这里面包括即时价值和固定价值(或最终价值)。即时价值是指用户故事的价值评判尺度会根据时间而减少,换句话说,这个用户故事在这两次迭代交付时是有价值的,而经过两次迭代后,它的价值就没这么大了,或者就根本不具备价值了;而固定价值或最终价值是指无论什么时候完成,这个用户故事都是有价值的,这个价值不会因为交付的时间变化而变化。
每个用户故事必须是可估计的,这样才可能安排下一步的开发计划。在一般情况下,让团队感到难以估计可能是因为用户故事的规格较大、所包含的内容较多,这就需要对用户故事进行进一步拆分,分解成能够进行估计的粒度;或者是对领域知识的缺乏,这就需要和客户进行更多沟通,以便充分理解相关需求。
可估计基于有信心的承诺。当团队认为有信心完成用户故事的时候,就会给出一个估计的时间。如果缺乏必要的信息(包括团队自身的开发能力和对用户故事的理解程度),团队就无法进行估计。团队对用户故事可估计的判断直接体现出这个用户故事的风险,这个风险包含两个方面:一方面是团队自身对用户故事的理解及实现技术的信心程度;另一方面是有没有足够的细节支撑。当然,“估计”这一方式本身就是不准确的,我们要允许团队在实践中通过不断回顾反思来提升估计的准确性。
每个用户故事都有完成的定义(Definition of Done,DOD)和验收标准(Acceptance Criteria,AC),如果缺乏完成的定义或验收标准,用户故事就会因为永远“完不了”而变成“不可估计”,这也说明用户故事一定要具有完成的定义或验收标准。在实践过程中,我们更倾向于让验收标准变得可测,换句话说,一定要具备测试规格。比如,正确保存账户余额,如何定义“正确保存”?不同的开发人员、测试人员的理解不同,对用户故事的估计也不一样。虽然我们会在迭代规划会议之前做出估计,但如果估计的差异太大,理解不一致,仍然属于“不可估计”。所以,“不可测试”一定是“不可估计”。
在实践中,我们可以用以下3种方法在不同的阶段估计用户故事的大小。
(1)在团队刚成立或接收了新需求的时候,可采用T恤的型号作为衡量单位,来估计用户故事跨迭代的数量(粗略估计)。
·XS:一天之内可以完成。
·S:一天可以完成。
·M:一周可以完成。
·L:两周可以完成。
·XL:超过两周可以完成。
(2)可以根据更加细节的内容进行精细化估计,一般采用斐波那契数列来表示,在开始的时候,用数字代表人天:0.5,1,2,3,5,8,13…需要注意的是,如果团队采用“结对编程”的方式,那么2个人算作1人天。
(3)如果团队比较成熟,估计会比较稳定,这时候就会采用上一次迭代的某个用户故事作为1点来估计本次迭代的用户故事,此时1点是一个比较单位,意思是基于上次迭代的某个用户故事为这次迭代进行估计,此时1点就不代表1人天,可能代表2人天,也可能代表0.5人天,具体数值应具体参考团队速率。所以,用户故事的点数不是一个用来评估工作量的工具,而是一个评估交付风险的工具。
一个好的用户故事应该在工作量上保持比较小的规模,而且需要确保在一次迭代内能够完成,超过这个范围的用户故事可能会在估计时出现很多错误,这时就需要将其拆分为更小粒度的用户故事。
用户故事的粒度决定了交付的风险,当我们认为一个用户故事很大的时候,往往是指无法保证将其按期交付,此时应将用户故事拆分成更小的用户故事,直到团队有信心按期交付,否则会给团队带来交付压力,增加交付风险。
在实践中,我们会根据故事点和迭代综合考虑用户故事的最小粒度范围,然后让团队承诺能够完成的用户故事数量。测试人员一定要启发团队成员考虑和讨论各种细节,并且积极与用户确认,切忌承诺无法实现的交付时间。
一个用户故事必须是可测试的,只有通过测试才能验证用户故事是否已经完成。我们不能开发一个不可测试的用户故事,不然怎么才能知道这个用户故事是完成了,还是没有完成呢?
一般来说,用户故事需要设定验收标准。测试人员最好能和客户一起讨论和制订验收标准,这样才能更好地了解这个用户故事到底需要测试什么、测试完成的标准是什么等关键信息。另外,在验收标准中,除了针对正常的“快乐路径”相关场景,还特别需要注意增加异常的场景,使整个验收标准更加完善。
在实践过程中,我们会将验收标准转化为验收测试。验收标准是用户的语言,而验收测试是开发团队的语言。验收标准往往很模糊,需要通过测试的方式明确,在这个过程中,用户能够进一步想清楚自己要什么。例如,用户故事的验收标准是“我可以隐藏登录界面”,这个验收标准描述的是一种能力,于是验收测试可以写为“当我在登录界面时,我点击‘隐藏’按钮,登录界面消失;再点击‘登录’按钮,登录界面出现”。
当然,关于登录界面、“隐藏”按钮、界面消失的方式和方法还需要进行进一步讨论与确认,直至与用户就最终的解决方案达成一致。在实践中,不同用户对于验收标准的明确程度有不同的要求,有些用户关注细节,所以与这类用户讨论用户故事所需要的周期就会相对较长,而另外一些用户就不太介意具体的实现方式,这也和相互之间的信任程度有关,敏捷软件的开发过程也是一个不断提升信任程度的过程。
还有一个关键点,即我们假设提出参与用户故事讨论的用户和最终验收的用户是同一个人。但如果提出人和验收人不是同一个人,就会出现问题,例如,在集体讨论时,所有的意见都由业务代表负责提出,但业务代表未必是最终负责验收的人。这往往会导致信息失真,双方不能达成一致,最后开发出来的软件也不是最终用户想要的。
以上问题的解决方法有如下3种。
(1)让验收人参与用户故事讨论。
(2)促使提出人和验收人之间达成验收一致。如果他们之间存在矛盾,那么开发团队不承担责任。
(3)若验收标准变更,则重新开始。
关于验收测试驱动开发(TDD),我们会在6.2节中详细介绍。
一句话总结,用户故事不是一个新的需求,而是开发人员和用户讨论需求的一种沟通工具。
在了解了用户故事后,接下来从测试的角度分析一个用户故事在全生命周期下,测试应该如何进行。用户故事将会按照生命周期的不同阶段被分成2种状态:当用户故事还在产品待办列表中时、当用户故事被放到一个Sprint待办列表中时。而当用户故事在Sprint待办列表中时,我们又可以再将其划分为不同的状态,细分情况如下。
(1)已定义:是指该用户故事被确定在本次Sprint中开发。
(2)处理中:是指该用户故事被开发和测试的过程。
(3)已完成:是指该用户故事已经被开发和测试完成。
(4)已接受:是指该用户经过产品负责人和利益干系人的验收。
当用户故事处于以上4种不同的状态时,测试人员需要执行什么活动,以及需要关注哪些点,可以参考表4-1。
表4-1 基于用户故事生命周期的测试关注点
关于用户故事的状态描述,有以下3个概念问题需要特别阐明:用户故事验收测试和我们常说的用户验收测试是不是一回事?DOR和DOD有什么区别?DOD和AC到底有什么不同?下面将对此进行详细介绍。
我们经常会看到“用户故事验收测试”这一描述,这实际上主要是针对每个用户故事的验收标准进行的测试。虽然用户故事的验收标准一般只有几个,但是真正在做验收测试的测试用例数量比验收标准要多得多,因为还需要设计很多异常测试用例,而这些是产品负责人不知道的。
用户验收测试是内部测试通过后,在最终用户或最终用户代表验收前进行的测试,它是从最终用户的角度进行的测试,验证产品是否满足用户的真正需要。
DOR(Definition of Ready)中文译为准备就绪的定义,是指我们在梳理用户故事的时候,应该确保产品待办列表顶端的用户故事已准备就绪,可以随时放入Sprint中让开发团队进行任务拆分和开发。在一般情况下,DOR会有一个检查表,其中包括检查是否清楚表达业务价值、是否有足够的细节、是否识别出依赖关系、验收标准是否清晰可测试、性能标准(如果有)是否已定义且可测试等。
DOD(Definition of Done)中文译为完成的定义,是指在宣布完成某项活动或潜在可发布产品之前,团队需要完成的各项工作检查。DOD有多种类型,可以是版本发布(Release)的DOD,可以是Sprint迭代的DOD,也可以是针对用户故事的DOD。例如,Sprint迭代的DOD一般包含设计评审是否完成、代码是否完成、测试是否完成、缺陷是否为零、用户文档是否已更新等。在某种程度上,DOR和DOD与准入标准、准出标准具有相似之处。
DOD主要针对我们在Sprint期间正在开发的产品增量。产品增量由一组用户故事组成,而每个用户故事都必须与DOD中列出的检查项保持一致。
AC(Acceptance Criteria)中文译为验收标准,是指用户故事必须满足的一组条件,只有达到这些条件,需求才算被实现了,它以需求本身为出发点来考虑功能的实现程度。所以,AC是对DOD的补充,而不是对其的替代。只有同时满足特定的用户故事验收标准(通过了验收测试)和DOD(如设计和代码通过评审、验收测试通过、用户文档更新等),才能认为这个用户故事真正被完成了。
在了解了敏捷需求后,接下来讨论测试计划。前面的内容介绍了敏捷测试方法和传统测试方法的一个重要区别出现在测试计划方面。传统测试方法会在项目前期就开始制订非常细致的测试计划,把测试中的各种因素都考虑进去。这种做法在一个项目范围可控、需求相对明确的环境下是可行的,但是在敏捷环境中,项目在最初阶段对于涉及的范围没有清晰地划分,也给出没有明确具体的需求,因此无法按照传统方式制订出详细的测试计划。这时就应该采用敏捷测试计划策略,也就是在项目初期的产品愿景规划中,只根据产品待办列表的粗粒度需求(如史诗、特性等)完成粗粒度的概要测试计划,不做详细计划。
随着项目不断推进,团队对需求和产品待办事项进行进一步梳理,为最接近当前Sprint周期的最高优先级用户故事添加更细的粒度,至于不那么紧迫、超出近期实现范围的需求,则可以留在更高的级别,直到其接近待开发周期。与此同时,我们也需要不断优化之前粗粒度的测试计划,把它变成为“Just-In-Time”的测试计划,敏捷测试计划策略如图4-1所示。
图4-1 敏捷测试计划策略
从图4-1可知,在项目初期主要依据项目的愿景和目标、产品路线图,以及当前已经掌握的颗粒度较大的主题、史诗和特性等需求制订粗粒度的概要产品测试计划,这个计划不需要全面细致,其主要作用是完成里程碑决策。参与制订计划的角色可能是业务相关利益干系人、产品负责人、业务分析师和Scrum Master等。如果在项目开始时,开发团队已经成立,那么建议团队成员也参与计划的讨论和制订。
随着项目不断进行,我们还会进行版本规划,一般一个版本的周期为1~3个月。在这个过程中,我们需要不断了解和梳理需求,通常会通过产品待办列表梳理活动,不断细化史诗、特性或用户故事。当我们对需求的了解程度越来越高,我们的测试计划也会越来越细化,而测试计划细化的主要依据是本次版本需要完成的需求列表、当次的版本计划和概要产品测试计划等。参与这个过程的角色可能会是产品负责人、业务分析师、Scrum Master、开发人员、Sprint内测试和跨Sprint测试工程师等。
当进入当次Sprint时,我们会以当次Sprint需要完成的用户故事列表、当次Sprint计划和当次Sprint所在的版本测试计划为依据细化Sprint测试计划。参与这个过程的角色可能会是产品负责人、业务分析师、Scrum Master、开发人员、Sprint内测试和跨Sprint测试工程师等。
在每日Scrum中,我们会根据每日站会的反馈、每日用户故事和任务处理的状态等信息判断是否需要更新测试计划,如果需要,那么应该适时更新。记住,测试计划只需描述对本次测试有意义的内容,避免将其做成一份大而全,却包含太多没有实际意义的计划,也就是说,我们需要的是“Just-In-Time”的测试计划。参与这个过程的角色可能会是产品负责人、业务分析师、Scrum Master、开发人员、Sprint内测试和跨Sprint测试工程师等。
传统测试计划是一次性的计划,可以被看成一个事件,测试计划文档在完成后基本不会再修改,因而被称为“死”文档。而敏捷测试计划是一个过程,需要不断地更新和细化,随着项目不断推进,计划也会越来越清晰准确。所以,敏捷的测试计划的英文为Test Planning而不是Test Plan,它是一个持续的过程,测试计划文档也应该是“活”文档。
在了解了需求和测试计划后,现在继续了解测试任务。当包含了验收标准的用户故事被定义好后,如果还是根据用户故事来追踪和度量,就会显得颗粒度比较粗,因此需要针对用户故事的实现进行任务分解。在每个Sprint计划中,我们需要把用户故事拆分成不同的任务,当次Sprint需要完成的用户故事列表加上拆分出的任务列表,最终形成了当次Sprint的待办列表。例如,我们为某用户故事创建了三个任务:第一个是开发功能的任务,我们会把此任务分配给开发人员;第二个是编写此用户故事的验收测试用例,会分配给Sprint内测试工程师;第三个是开发自动化测试验收脚本的任务,涉及自动化框架和脚本的开发,会分配给测试开发工程师。用户故事拆分任务示意图如图4-2所示。
在跟进敏捷测试任务的过程中,一定要注意以下3点。
(1)DOD:当我们把一个用户故事拆分成开发任务、测试任务等时,判断一个用户故事是否完成的标准是这个用户故事下面所有的任务是否都已完成。不能只以开发完成为标准,而是要经过测试并确认没有问题后,才可以宣布该用户故事已经完成。这一点和我们对传统项目的认识有很大区别,而且也充分回应了前面敏捷测试定义的内涵之一:在测试融入开发的过程中,直到功能开发和测试执行完成了,用户故事才能被认为是完成了。
图4-2 用户故事拆分任务示意图
(2)可见性:敏捷的一个关键点是透明性或可见性,也就是说,不同类型的工作,包括正在完成的用户故事和自动化测试的进展应该是清晰可见的。在实现这一点时,一般会采用看板将工作任务可视化(相关的内容请见4.4.2节)。
(3)可跟踪性:可跟踪性无论在传统瀑布式项目还是在敏捷项目中都非常重要。一旦实现了可跟踪性,如果项目上线后出现一个缺陷,我们就可以很快找到该缺陷是在实现哪个用户故事时产生的、关联哪一段代码、哪个测试用例漏测等信息,这对于定位和修复缺陷、做缺陷根源分析可以起到很大帮助。因此,我们需要将开发过程的所有工件建立链接关系,这样才能实现可跟踪性。由于可跟踪性的维护和管理比较烦琐,一般我们会采用管理工具(如Jira)来实现可跟踪性这一功能。
最后,再来看对于测试人员来说,在一个完整的版本发布周期中有哪些敏捷测试任务,如图4-3所示,这些需要他们格外留意。
图4-3 版本发布周期的敏捷测试任务
敏捷强调透明,针对我们的工作任务,一般会通过看板的方式进行可视化及透明化管理。看板也被称为“Kanban”,是一个与精益生产相关的概念。第一个看板系统是在20世纪40年代初由大野耐一为日本的丰田汽车公司开发的,它作为一个简单的计划系统创建,其目的是在生产的各阶段最优控制和管理工作与库存。通过看板,丰田汽车公司拥有了一个灵活高效的即时生产控制系统,在提高了生产率的同时减少了库存。
看板是由大野耐一从制造业引入的概念。2004年,David J.Anderson第一个将其应用于IT软件开发,他在大野耐一、戴明等质量大师的著作的基础上定义了看板方法,同时提出了拉动系统、排队论和流等概念。Anderson在2010年出版的第一本关于看板的书—— Kanban:Successful Evolutionary Change for Your Technology Business 给出了软件开发看板方法的最全面定义。
看板方法遵循一组管理和改进工作流程的原则和实践,这些实践可以帮助我们改进流程、减少周期长度、增加客户价值,以及带来更大的可预测性。看板的核心要素始终植根于以下4个原则。
通过创建工作和工作流程的可视化模型,观察通过看板系统移动的工作流程。将工作与阻塞程序、瓶颈和队列一起公开,可以立即增进团队成员之间的信息交互和协作,有助于团队了解成员工作的进展速度,以及可以在哪里集中精力加快流程。
看板的一个关键是减少大多数团队或知识工作者认为的多任务并发状态,鼓励他们“Stop Starting”和“Start Finishing”。在工作流程的各阶段限制在制品(WIP)数量,其意义是鼓励团队成员优先完成当前工作,然后再开始下一项,从而避免工作积压,即通过限制流程中的未完成工作数量来减少任务通过看板的时间。同时,还可以避免由任务切换引发的问题,并且减少不断对任务进行重新排序的需要。WIP释放了看板的全部潜力,使团队能够在更健康、更可持续的环境中更快地交付高质量的工作。
看板的核心是“流”的概念,这意味着卡片应该在系统中尽可能均匀地流动,不出现长时间等待或阻塞,所有阻碍流动的因素都应该仔细检查。“流”的概念至关重要,通过对“流”指标进行度量及改进,可以显著提高交付流程的速度,同时从客户方较快地获得反馈,减少周期长度并提高产品或服务的质量。
一旦看板就位,其将成为组织之后持续改进的基石。团队通过跟踪流程、质量、吞吐量、交付时间等来度量其有效性,提高团队的效率。持续改进是一种精益改进技术,可以帮助简化工作流程,节省整个企业的时间和资金投入。
看板是一种非破坏性的演进式任务管理系统,这意味着要对现有流程进行小步骤的改进,即通过许多较小的更改,减少整个系统的风险。看板的演进方法带来了团队和涉众的低阻力或零阻力。
引入看板最重要的是可视化工作流程。看板由简单的白板和便利贴或卡片组成,白板上的每张卡片代表一个任务,在一个经典的看板模型中,存在以下3栏。
(1)To Do:这一栏列出了尚未开始的任务。
(2)Doing:这一栏列出了正在进行的任务。
(3)Done:这一栏列出了已完成的任务。
另外,Doing上方的数字“5”表示限制在制品(WIP)为5,也就是同一时间最多只能处理5个任务,看板示例如图4-4所示。
图4-4 看板示例
这个简单的看板通过可视化使工作分布及现在面临的瓶颈变得清晰。当然,更复杂的或特定的看板系统可以根据工作流程的复杂性,以及可视化和特定工作流程来定制。以下是一个敏捷项目的任务看板示例,如图4-5所示。
图4-5 敏捷项目的任务看板示例
本节给出在一个敏捷Scrum的Sprint周期内的测试和DevOps等相关活动的日程安排。该案例是某大型国外客户的分布式敏捷开发项目,每个Sprint周期为2周,开始时间为第一周的周四,结束时间为第二周的周三,其敏捷测试活动日程安排如图4-6所示,其中,粗体部分是团队的里程碑,铺灰部分是与DevOps相关的工程活动,而其余是主要的测试活动。
图4-6 敏捷测试活动日程安排
有4个关键点需要特别说明。
(1)Sprint的起始时间。此案例以周四为起始日,而通常的生活习惯是以周一作为一个星期的开始。那么,为什么这里会选择周中作为起始日呢?一种说法是如果Sprint是每2周为1次迭代,那么Sprint中就包含了2个周末,而这2个周末可以被当作本次Sprint的缓冲,如果进度落后,那么还可以利用周末加班。但在该案例中,外国人不大可能牺牲周末加班赶进度,之所以选择周四作为Sprint的起始日,是因为Sprint的结束日将会在周三,可以预留周四和周五2个工作日进行上线,如果上线有问题,那么还可以在工作日进行修复。而如果选择周一作为起始日,那么意味着周五是结束日,如果周五晚上上线时出现问题,安排人员在周末处理会比较困难。
(2)产品负责人在第一周结束时和团队有一个接触点,他们不会在参加完Sprint计划会后,等到2周后的Sprint演示阶段才参与进来,而是在这个接触点确保团队在本次Sprint中做的工作是正确的,并且接下来的工作也会按计划进行。如果在这个接触点发现出现了偏差,那么就要尽快采取行动纠偏。
(3)在第二周周中会进行下一次Sprint的用户故事梳理活动,确保在下一个Sprint计划到来时,用户故事已经变得比较具体详细,以及已满足DOR的条件。
(4)在整次Sprint中,测试活动和DevOps活动是紧密联系的,它们共同支撑了项目的质量保障工作。
度量是赋予一个对象或事件的数值特征,可以通过数值与其他对象或事件进行比较。度量是一种很好的手段,可以检验我们距离目标到底有多远。如果项目不进行度量,我们就无法知晓当时的状态和目标相比到底是落后了还是超前了,是偏差了还是符合要求。因此,我们常常把度量当作一种“路标”,用其衡量团队是偏离了“轨道”,还是在沿着正确的“轨道”前进。但是,在使用度量的时候,我们应该警惕以下2个误区。
如果把度量用在对个人的绩效评价上,那将会是一件非常危险的事情。个人为了完成绩效指标势必会想方设法来满足指标考核要求,比如,如果我们对开发人员每天开发的代码量(行数)做考核,开发人员很有可能会为了达到指标要求而开发大量的冗余代码,或者使代码逻辑不够简洁清晰,久而久之,代码的可维护性将变得很差,这种没有正确使用度量所造成的后果是我们不希望看到的。一旦把度量应用在个人考核方面,就很有可能会产生各种各样的负面效果。
因此,我们应当把度量用于团队目标,比如,我们关注自动化测试的通过率是为了检验当前版本到底离希望达到的质量目标还有多远,而不是为了证明开发人员写的代码有多差。另外,需要记住的是,我们应当把度量当作一种正向的激励手段,而不是惩罚别人的证据,否则一定不会得到客观的结果。
只对单个指标进行割裂的分析没有任何意义,比如,测试人员在测试过程中发现了很多缺陷,这说明什么?有可能说明测试人员的能力强;也可能说明不是测试人员厉害,而是开发人员太差,写的代码存在很多问题;还有可能是因为此模块本身就很复杂,难度高,所以出现的缺陷当然比开发一个简单功能的模块多。因此,如果不是从全局的角度对多个指标进行综合性分析,只看单个指标很难知道真正的根源是什么。只有综合其他指标,运用全局性思维进行分析,才能透过这些指标获悉项目的真实情况,才有助于接下来采取正确的行动。
那么,与敏捷测试相关的度量指标有哪些呢?以下为部分参考指标。
(1)代码覆盖率:是指由开发人员在单元测试过程中,运行单元测试用例时所执行的代码量占该模块总代码量的百分比。目前,有很多工具可以自动化地统计这个度量值,比如,JaCoCo就是一个用于Java语言的代码覆盖率统计工具。需要注意的是,代码覆盖率指标不能一味追求100%。Martin Fowler等众多专家都认为追求100%的代码覆盖率是没有意义的,因为它不代表代码的真实质量。代码覆盖率的真正意义是帮助发现代码还有哪些部分没有被测试,因此,一般能够达到80%以上就已经很好了。
(2)验收测试通过率:是指某版本(一次Sprint或Release)中通过验收测试的用户故事数占总用户故事数的百分比,该指标主要用来衡量当前版本的需求总体完成情况,以及是否达到发布条件。因为只有通过验收测试的用户故事才算完成,所以我们可以较为容易地统计出本次版本的需求完成情况。另外,对于是否可发布,除了要关注验收测试通过率,还要关注最小可发布特性集(MRF)。MRF指在一个版本内最少必须要实现的需求集,否则无法实现本次版本目标。MRF中的需求必须全部完成,这是必要条件,而不是充分条件。
(3)每用户故事点缺陷率:是指某版本(一次Sprint或Release)发布后在其中发现的缺陷数(可以定义为发布后一段时间内发现的缺陷,如两周内)除以当次版本用户故事点的总数,该指标用来度量版本的总体质量,可帮助分析版本质量是否随着迭代的增加而逐渐提升。
(4)验收自动化率:是指通过自动化测试来验收的用户故事数占总用户故事数的百分比,该指标主要是考核自动化的实施情况。应该鼓励把能自动化的验收测试都尽量自动化,自动化的程度越高,进行回归测试的效率越高。
本章从测试的角度讨论了在敏捷项目下测试的相关活动,包括从测试需求、测试计划、测试任务分解与跟踪,以及从用户故事生命周期的维度讨论了测试涉及的活动。
本章的主要内容如下。
(1)一个好的用户故事需要遵循INVEST原则。
(2)判断一个用户故事是否完成,不是以开发完成为标准,而是要经过测试并确认没有问题后,才可以判定用户故事已经完成。
(3)敏捷测试计划策略是指在愿景规划和待办事项梳理中,只需完成粗粒度的测试计划,随着项目的推进不断对待需求进行梳理,为“最接近Sprint周期”的最高优先级用户故事添加更细的粒度,而不那么紧迫的、超出范围的工作可以放入更高的级别,直到它接近待开发周期。同时,将优化之前粗粒度的计划变为粗细适中的“Just-In-Time”的测试计划。
(4)敏捷需要具有透明性或可见性,不同类型的工作,例如,正在完成的用户故事和自动化的进展,都应该清晰可见,并且可以通过看板呈现。
(5)看板的4个核心原则分别是可视化、限制在制品(WIP)、管理“流”和持续改进。
(6)要度量团队目标而不是个人绩效,要全局性分析指标组合而不是割裂分析单个指标。