端到端测试
任何类型的自动化功能测试,都需要一个完美的平衡点。测试执行的功能越多,测试的范围越广,我们对应用程序的信心就越高。另一方面,测试范围越大,测试运行的时间就越长,同时在测试失败时找出失败的原因就会越困难。
就其覆盖的功能而言,任何类型的系统的端到端测试的覆盖范围都是最大的。并且我们通常认为,相比与覆盖范围更小的单元测试而言,端到端测试更难以编写和维护。但是,端到端测试通常是值得的,因为我们希望通过执行像用于一样使用我们的系统的端到端测试来获得信心。
但是,使用微服务架构时,我们的端到端测试的“范围”变得非常大。现在,我们必须跨多个服务运行测试,所有这些服务都需要为测试场景而部署并做适当的配置。我们还必须为环境问题(例如服务实例停止运行、部署失败的网络超时)导致的测试失败进而产生的错误判断做好准备。我认为与标准的单体架构相比,在针对微服务架构进行端到端测试时,我们更容易受到无法控制的问题的影响。
随着测试范围的扩大,我们将花费更多的时间来应对出现的问题,以至于尝试创建和维护端到端的测试变得非常耗时。
该问题如何表现出来
一个迹象就是:端到端的test suite不断增加,并且需要越来越长的时间才能完成测试。这是由于多个团队无法确定覆盖的测试场景,而为了“以防万一”而增加新的test suite。我们会在端到端的test suite中发现更多的测试失败,这些失败并没有突出标记出代码问题——所以,开发人员常常只是再次运行测试以查看是否通过。
花费在端到端测试上的时间越来越长,以至于我们开始看到更多测试人员甚至是单独的测试团队所面临的压力。
该问题何时发生
这个问题往往会悄悄地出现,但是我发现,在由多个团队处理用户的不同操作时,该问题表现的最为强烈。每个团队的工作越独立,他们就越容易在本地管理自己的测试。越是需要跨团队的测试流程,大范围的端到端测试就越是问题。
该问题的解决方案
在《Building Microservices》一书中,我概述了很多方法来帮助我们改变测试的方法。实际上,在书中,有一整章专门对其进行了介绍。但是,此处有一个帮助大家入门的简短的摘要。
限制功能自动化测试的范围
如果要编写覆盖多个服务的test case,请尝试确保将这些测试限制在管理这些服务的团队内部。换句话说,要避免跨团队边界的、更大范围的测试。将测试的所有制控制在一个团队内部,可以:
- 更容易地了解正确覆盖了哪些场景
- 确保开发人员可以运行和调试测试
- 更清楚地阐明了谁应该为确保测试可以运行并通过而负责
使用消费者驱动的契约
可能会考虑使用消费者驱动的契约(CDC: consumer-driven contracts)来代替跨服务的test case。使用CDC,可以让微服务的使用者根据可执行的规范来定义他们所期望的我们的服务的行为,该可执行的规范就是一个测试。我们在修改服务时,要确保这些测试仍然是通过的。
由于这些测试是从消费者的角度定义的,因此我们可以很好地弥补意外的契约破坏。我们还可以从消费者的角度了解他们的需求。重要的是可以了解:不同的消费者可能希望从我们这里获得不同的东西。
可以使用简单的开发流程来实现CDC,但是可以使用支持该技术的工具来简化CDC。最好的工具可能是Pack。
值得注意的是,我已经发现很多团队利用CDC取得了巨大成功,但是对于其他的团队而言,采用CDC却非常困难。CDC是合理的,我知道,它可以很好地工作。但是,我还没有完全理解某些人在采用这种技术时所面临的挑战。对于解决一个非常困难的问题,CDC仍然是一种未被充分利用的实践。
使用自动发布修复和渐进式交付
利用自动化测试,我们通常试图在问题影响产品之前就发现问题。但是,随着系统变得越来越复杂,做到这一点也变得越来越困难。因此,如果确实发生了线上问题,则值得花费精力来减少其影响。
正如我们在第3章中谈到的那样,渐进式交付是用于控制如何以增量方式向客户推出软件的新版本的总称。渐进式交付的想法是,我们可以用一组少量的客户来评估新版本的影响,并确定是否以及何时可以继续发布新版本或者回滚新版本。渐进式交付的例子是金丝雀发布。
通过为“服务应该如何表现”定义可接受的度量,就可以用自动化的方式控制渐进式交付。举一个简单的例子,可以把95分位的延迟和错误率定义为可接受的阈值,并且仅在满足这些指标时才继续发布新版本。否则,可能会自动回滚到最近的版本,从而让我们有时间去分析所发生的事情。
许多组织使用了这种自动发布修复技术。特别的,Netflix公司就对使用该技术做了详尽的介绍。Netflix开发了Spinnaker作为部署管理工具,该工具可以帮助控制服务的渐进式交付,但是可以通过许多其他的方式将这些想法付诸实践。
我并不是说应该考虑自动发布修复,而不是进行测试。我只是说,要考虑可以从哪里获得最大的收益。如果问题确实发生了,将工作置于问题的捕获而不是仅仅着眼于阻止问题的发生,可能最终会得到一个更强大的系统。
需要注意的是,尽管这些技术可以很好地协同工作。即使我们认为自动修复不是我们需要马上去做的事情,但实施某种形式的渐进式交付仍然具有巨大的价值。即使只是手动控制渐进式交付,也可以在仅将新软件发布给所有人上迈出了一大步。
持续提升质量反馈周期
了解如何测试以及在何处测试是一个持续的挑战。需要有背景(context)的人在整个开发过程中全面了解,以适应应用程序的测试方式和位置。这意味着我们需要这样的人员:
- 当他们发现产品在某个区域的缺陷不断增加时,他们能够识别出需要增加新的测试来覆盖该区域的需求。
- 在努力提升质量反馈周期时,当他们发现有的测试已经被覆盖到时,他们也需要删除该测试。
简而言之,这是关于平衡快速反馈与安全性的事情。需要像添加新测试一样去识别、删除、替换错误的测试。