@levinzhang
2018-05-30T11:45:31.000000Z
字数 4672
阅读 709
by
reviewed by
微服务的测试不应该由专门的测试团队在一个单独的测试阶段中完成,相反,它应该由跨功能的团队协作完成。在测试领域现在有两种转变,一种向左的转变,它会确保团队保持自治,另一种是向右的转变,它侧重的是探索性和实验性。持续测试和实验性的文化能够推动微服务的发布更快更可靠。
架构会对测试带来重要的影响。测试单体系统的方式与测试松耦合系统的方式是不同的。我们以微服务作为松耦合系统的典型示例。下面将会看到,它们挑战了我们之前对于测试的定义。
Melvin Conway观察到组织的结构会对它们所创造的产品带来显著的影响:“任何组织在设计一套系统时[……],所交付的设计方案在结构上都与该组织的沟通结构保持一致。”
康威定律说明公司的软件架构通常会反应组织的结构。另一方面,我们如何组织团队会对架构和测试方法带来巨大的影响。
架构和组织结构之间的互相依赖也会反映到BAPO模型中,该模型假设在软件工程中,需要解决四个关注点:业务(Business)、架构(Architecture)、过程(Process)和组织(Organization)。从根本上来说,这个理念是基于业务需求来定义架构。但是,正如Jan Bosch(2017)所言,大多数的公司并不符合BAPO,而是遵循OPAB,也就是以组织结构作为基础来定义架构。
如果组织想要改变软件产品的架构的话,那么它的组织结构(包括测试如何组织)可能是一个推动者,也可能是一个障碍。让我们看一下不同类型的组织结构:
关于这方面的更多信息,参见:Gene Kim(2016)。
像微服务这样的松耦合架构该如何进行测试呢?
松耦合的系统遵循服务自治的原则,因为它的架构就是基于各个自治的组成部分分解而成的。
越来越多的组织在采用微服务,以便于提升团队的自治性并加快应变的速度。微服务应用由小型、版本独立且可扩展的服务组成,这些服务以客户为中心,它们彼此之间以定义良好的接口通过标准协议进行通信。
微服务
这对测试意味着什么呢?
如果我们面向领域并且针对每个业务功能进行垂直切分,那么依然可以有分层的架构,但是层是次要的组织机制。自治的产品开发团队负责实现、测试和交付业务功能:
微服务通常会伴随着DevOps:在敏捷和DevOps中,在开发阶段开始之前,并没有架构师定义整体架构的单独设计阶段。相反,架构会以更加联合的方式来定义,跨越多个项目,并且被整个团队所拥有。
那么这些系统的测试方式又会发生什么样的变化呢?同样,测试不会在一个单独的测试阶段来完成。与之相反,每个人都要为质量负责。
没有独立的测试阶段:
DevOps和持续集成&持续交付(Continuous Integration & Continuous Delivery,CI & CD)解决了快速且高质量为客户交付功能的需求。这意味着测试必须要提供快速和有意义的反馈。为了快速且有自信地发布版本,需要从持续测试(Continuous Testing)中得到立即的反馈:
图片来源:Dan Ashby (2016)
测试并不是一个隔离的活动,而是集成到一组综合的实践中,以便于提升质量:“依然有很多的公司在努力改变流程以提升质量,从‘测试或检查质量’转变到一开始就保证高质量,这要通过文化、设计、工艺以及领导力才能实现”(Ben Linders 2017)。
开发人员在确保高质量方面扮演了重要的角色,另外,软件工艺原则也能促进质量的提升。软件工艺指的是软件开发过程中专业性:“工艺精湛的软件意味着,不管应用多么古老,开发人员都能很容易地理解。它的副作用众所周知并且能够得到控制。具备很高很可靠的测试覆盖率,设计清晰简洁,代码能够很好地表达业务语言”(Sandro Mancuso,2015)。
持续测试(通常)意味着向左转和向右转:
向左转和向右转是什么意思呢?
测试通常是按照特定的顺序执行的,从(左侧的)单元测试开始,因为它们能够提供快速的反馈,后续的测试则需要更长的时间来执行,但是它们能够增加我们对候选释放版本的自信心:
在这里,有一种左转的趋势,那就是自动化单元和组件级别的测试,在持续集成&持续交付(CI & CD)管道中执行,这个管道是由产品开发团队所拥有的。但是,这是有其成本的:考虑到集成场景的复杂性和动态性,集成测试会变得更加具有挑战性。
如果我们要对比讨论隔离状态以及基于协作的测试,那么很重要的一点就是要区分独立性的(solitary)和社会性的(sociable)测试方式:
按照测试金字塔的理念,微服务测试的关注点在于要有很多的单元测试以及一组全面的组件测试。微服务首先会彼此隔离地进行测试,然后进行少量的集成,最后是端到端测试。很多端到端测试通常被视为一种问题,因为它们的执行比单元和组件测试要耗费更长的时间,并且也会更加脆弱。但是,很有意思的一点在于,有一种关于测试金字塔理论对微服务测试的价值的争议,以及如果关注单元和组件测试,并使用它们来替代集成测试是否依然是合理的(参见样例:Cindy Sridharan 2017和André Schaffer 2018)。这是一个合法性的问题,因为如果微服务的集成是最具挑战性的,那我们是否可以不要更多关注集成测试,而是更多的依赖社会化的测试?我认为,答案可以说是也可以说不是:如果微服务的嵌入式依赖没有提供独立的业务功能,那么将微服务与这些依赖一起进行测试是非常有意义的。在微服务中,这种类型的社会化测试应该在与其他微服务的集成测试展开之前完成,其他的微服务会封装别的业务功能。如果没有足够的单元和组件级别的测试,分析集成测试的故障会更加复杂。同时,除了传统的集成测试以外,API以及契约集成测试也是非常重要的,因为它们有助于保证微服务协作管道之间能够互相独立。因此,在合适的测试等级进行测试是非常重要的。
另外一个方面也很重要:对于微服务来说,集成场景是复杂和动态的,要有多少集成测试才够用呢?将更多的精力投入到测试中以及在生产环境中快速探查问题之间要有一个权衡。除了左转之外,还有一个趋势,那就是将测试与生产环境的部署和监控更加紧密地连接在一起。生产环境的核对实验(controlled experiment)有助于快速识别问题并得到真实用户的快速反馈。
不同类型的生产环境流量测试有何差异?
这意味着在测试方面还有向右转的趋势。
如前文所述,面向市场的组织针对速度进行了优化,在测试领域的右转有助于完成他们的目标。作为持续实验的一部分,可以进行探索和学习。借助核对实验,在现实中使用应用程序的时候,我们能够得到客户的反馈。
核对实验也能支持弹性架构。正如我们在前面所讨论的,微服务应该通过自治实现可靠性和故障隔离。但是什么是弹性呢?“我们通常认为脆弱系统的对立面就是健壮的系统,因为脆弱的系统通常不会过多(换句话说,说不上喜欢或不喜欢)关注压力。实际上,健壮的系统仅仅脆弱程度有所降低而已。脆弱系统真正的对立面是能够从压力中受益的系统。Nassim Taleb将这样的系统称为反脆弱(antifragile)的”(Dave Zwieback 2014, p. 3)。传统的测试方式是在版本发布之前对系统进行测试,以确保稳定性。但是,这些测试能够支撑健壮性,但是无法支撑系统的“反脆弱性”。有种不同的测试方式就是在生产环境中引入故障,运行主动可控的混乱(chaos)实验。这种精心设计的混乱能够指导产品开发团队思考故障的容忍度和隔离故障的可能性。
对于微服务这样的松耦合系统,测试不应该在一个单独的测试阶段由专门的测试团队来进行,而应该由跨职能的产品开发团队来完成。在测试中,有一种向左的转变,确保团队能够保持自治,同时还有一种向右的转变,这种转变强调的是探索性和实验性。
持续测试(Continuous Testing),既包括CI & CD中的自动化测试,还包括实验性和探索性的文化,它能够保证快速且稳定地发布松耦合的服务。
Stefan Friese是HERE的测试与研发主管,目前在柏林工作。在当前的职位中,他带领团队为一些实时位置的Web服务来构建持续集成&交付的测试功能,这些服务托管在HERE云平台上。Stefan有着14年的工作经验,曾经担任过测试主管、性能测试人员、软件工程师以及质量工程师。你可以通过@y3key在twitter上关注Stefan的动态。