写点什么

符合架构的测试

Testing Microservices

2018 年 6 月 03 日

核心要点

  • 微服务通常属于跨功能且自治的团队,该团队负责微服务的实现、测试和发布。
  • 在实现微服务架构时,不应该有独立的测试阶段。
  • 每个人都要对产品的质量负责。
  • 微服务集成的复杂性要求我们谨慎地决定合适的集成测试方式。
  • 持续测试意味着要向左转变以确保团队保持自治,还要向右转变以实现探索性和实验性。

架构会对测试带来重要的影响。测试单体系统的方式与测试松耦合系统的方式是不同的。我们以微服务作为松耦合系统的典型示例。下面将会看到,它们挑战了我们之前对于测试的定义。

康威定律

Melvin Conway 观察到组织的结构会对它们所创造的产品带来显著的影响:“任何组织在设计一套系统时 [……],所交付的设计方案在结构上都与该组织的沟通结构保持一致。”

康威定律说明公司的软件架构通常会反应组织的结构。另一方面,我们如何组织团队会对架构和测试方法带来巨大的影响。

架构和组织结构之间的互相依赖也会反映到 BAPO 模型中,该模型假设在软件工程中,需要解决四个关注点:业务(Business)、架构(Architecture)、过程(Process)和组织(Organization)。从根本上来说,这个理念是基于业务需求来定义架构。但是,正如 Jan Bosch(2017)所言,大多数的公司并不符合 BAPO,而是遵循 OPAB,也就是以组织结构作为基础来定义架构。

如果组织想要改变软件产品的架构的话,那么它的组织结构(包括测试如何组织)可能是一个推动者,也可能是一个障碍。让我们看一下不同类型的组织结构:

  1. 面向功能的组织能够优化成本。这些组织一般会有层级的结构,结构中包含专家团队,他们负责其功能领域。
  2. 面向市场的组织能够优化速度。这些组织一般会比较扁平化,具备跨功能和自治的团队,他们负责实现和交付产品,不过这样有可能会导致在整个组织范围内产生冗余。
  3. 面向矩阵的组织试图将面向功能和面向市场的理念结合起来。

关于这方面的更多信息,参见:Gene Kim(2016)。

测试微服务

像微服务这样的松耦合架构该如何进行测试呢?

松耦合的系统遵循服务自治的原则,因为它的架构就是基于各个自治的组成部分分解而成的。

越来越多的组织在采用微服务,以便于提升团队的自治性并加快应变的速度。微服务应用由小型、版本独立且可扩展的服务组成,这些服务以客户为中心,它们彼此之间以定义良好的接口通过标准协议进行通信。

微服务

  • 是自治的并且真正松耦合,因为每个微服务都是与其他的微服务物理分离的。
  • 只负责一项功能(功能分解)。
  • 可以独立部署和发布。
  • 应该嵌入依赖,以确保集成点的数量是可管理的。
  • 应该能够通过自治性实现弹性和故障隔离。

这对测试意味着什么呢?

如果我们面向领域并且针对每个业务功能进行垂直切分,那么依然可以有分层的架构,但是层是次要的组织机制。自治的产品开发团队负责实现、测试和交付业务功能:

微服务通常会伴随着 DevOps:在敏捷和 DevOps 中,在开发阶段开始之前,并没有架构师定义整体架构的单独设计阶段。相反,架构会以更加联合的方式来定义,跨越多个项目,并且被整个团队所拥有。

那么这些系统的测试方式又会发生什么样的变化呢?同样,测试不会在一个单独的测试阶段来完成。与之相反,每个人都要为质量负责。

没有独立的测试阶段:

DevOps 和持续集成 & 持续交付(Continuous Integration & Continuous Delivery,CI & CD)解决了快速且高质量为客户交付功能的需求。这意味着测试必须要提供快速和有意义的反馈。为了快速且有自信地发布版本,需要从持续测试(Continuous Testing)中得到立即的反馈:

  • 所有的测试几乎都要是自动化的。对于 CI & CD 来说,启用持续测试是至关重要的,因为它提供了关于质量的及时反馈。同时,它能够让团队快速掌握和应对。
  • 但是,这并不意味着持续测试只与自动化测试相关。我们接下来将会看到,它是一个全面的方法,目的是得到质量的及时反馈:

图片来源:Dan Ashby (2016)

测试并不是一个隔离的活动,而是集成到一组综合的实践中,以便于提升质量:“依然有很多的公司在努力改变流程以提升质量,从‘测试或检查质量’转变到一开始就保证高质量,这要通过文化、设计、工艺以及领导力才能实现”(Ben Linders 2017)。

开发人员在确保高质量方面扮演了重要的角色,另外,软件工艺原则也能促进质量的提升。软件工艺指的是软件开发过程中专业性:“工艺精湛的软件意味着,不管应用多么古老,开发人员都能很容易地理解。它的副作用众所周知并且能够得到控制。具备很高很可靠的测试覆盖率,设计清晰简洁,代码能够很好地表达业务语言”(Sandro Mancuso,2015)。

持续测试(通常)意味着向左转和向右转:

向左转和向右转是什么意思呢?

测试通常是按照特定的顺序执行的,从(左侧的)单元测试开始,因为它们能够提供快速的反馈,后续的测试则需要更长的时间来执行,但是它们能够增加我们对候选释放版本的自信心:

在这里,有一种左转的趋势,那就是自动化单元和组件级别的测试,在持续集成 & 持续交付(CI & CD)管道中执行,这个管道是由产品开发团队所拥有的。但是,这是有其成本的:考虑到集成场景的复杂性和动态性,集成测试会变得更加具有挑战性。

如果我们要对比讨论隔离状态以及基于协作的测试,那么很重要的一点就是要区分独立性的(solitary)和社会性的(sociable)测试方式:

  • 在独立性的测试活动中,被测试的软件单元是隔离的,要将协作者(上游依赖)替换为测试替代品(test doubles),比如 mocks 或 stubs。
  • 在社会性的测试活动中,被测试的软件单元要与协作者一起进行测试。

按照测试金字塔的理念,微服务测试的关注点在于要有很多的单元测试以及一组全面的组件测试。微服务首先会彼此隔离地进行测试,然后进行少量的集成,最后是端到端测试。很多端到端测试通常被视为一种问题,因为它们的执行比单元和组件测试要耗费更长的时间,并且也会更加脆弱。但是,很有意思的一点在于,有一种关于测试金字塔理论对微服务测试的价值的争议,以及如果关注单元和组件测试,并使用它们来替代集成测试是否依然是合理的(参见样例: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 的动态。

查看英文原文: Architecturally Aligned Testing

2018 年 6 月 03 日 18:061363

评论

发布
暂无评论
发现更多内容

在线医疗的发展和优势

anyRTC开发者

android 音视频 WebRTC RTC 医疗方案

Canvas入门实战之用javascript面向对象实现一个图形验证码

徐小夕

Java 前端 canvas

硬核编程:30天=一个网站+一份周刊

老魚

程序员 建站 web全栈

盘点2020 | 30岁了,我终于入门编程了

希望

盘点2020

通过Postman和coding.net发布API

太极程序员

Postman API

DeFi(去)中心化DAPP系统软件开发

开發I852946OIIO

系统开发

智慧城市建设,社区智能化系统搭建解决方案

t13823115967

智慧城市 平安小区

DolphinDB与MongoDB在时序数据上的对比测试

DolphinDB

mongodb 分布式系统 时序数据库 DolphinDB 数据库开发

【经验分享】RTC技术系列之音频编解码

邵帅

码了2000多行代码就是为了讲清楚TLS握手流程(续)

Gopher指北

golang https

LeetCode题解:127. 单词接龙,BFS+统计单词变化次数,JavaScript,详细注释

Lee Chen

算法 LeetCode 前端进阶训练营

EZYTRX波场智能合约APP系统软件开发

开發I852946OIIO

系统开发

Java并发编程:多线程如何实现阻塞与唤醒

码农架构

Java并发

架构之书:雄伟与《Domain Driven Design》

lidaobing

架构 领域驱动设计

架构师训练营 Week8 - 课后作业

极客大学架构师训练营

量化交易APP系统软件开发(现成)

开發I852946OIIO

系统开发

架构师训练营W09作业

Geek_f06ede

Prometheus TSDB(Part 2):预写日志(WAL)和检查点

_why先生

云原生 Prometheus tsdb 可观察性

《大数据算法》.pdf

田维常

算法

腾讯高工强烈推荐的“Netty速成手册”原理+应用+调优,带你将知识点一网打尽

比伯

Java 编程 程序员 架构 Netty

生产环境全链路压测建设历程之十 淘宝网2013年的建设过程

数列科技杨德华

anyRTC实时音视频-社交娱乐解决方案

anyRTC开发者

ios android 音视频 WebRTC RTC

智慧社区系统开发方案,智慧平安小区综合管理系统建设

WX13823153201

智慧社区系统开发

答了Mybatis这个问题后,面试官叫我回去等通知……

田维常

mybatis

数据类型第2篇「字典和集合的原理和应用」

清菡

测试开发

Spring Boot 集成 Redis

噜噜猫

Spring Boot

【小菜学网络】数据链路层概述

fasionchan

网络编程 计算机网络 网络协议 TCP/IP

盘点2020 | 疫情下的思考和学习

soolaugust

盘点2020

如何快速打造一款钉钉 Go sdk

Ceelog

go golang 钉钉 企业微信

从零开始学习Java8 Stream,看这篇就够了

Silently9527

Java stream java8

SPI 在 Dubbo中 的应用

vivo互联网技术

Java jdk dubbo spi

演讲经验交流会|ArchSummit 上海站

演讲经验交流会|ArchSummit 上海站

符合架构的测试-InfoQ