0%

Hermetic Server

考虑一个复杂的web应用。实际上,其由一个服务器迷宫,每一个负责不同的任务,并且有这相互复杂的交互。每一个用户行为会游走“服务器迷宫”后返回给终端用户。我们应该怎么对这样应用写end-to-end测试用例呢?

End-To-End Test

一个end-to-end测试在Google的测试宇宙中指代:验证了整个从请求到响应间的全部服务栈。下面是一个简化的SUT(System Under Test)的示例,用以说明一个end-to-end测试用例用来验证什么。注意SUT中的Frontend Server与一个第三方服务相连,但示例中的请求是不需要这部分信息的。

SUT-1

对这么一个系统,要写一个又的end-to-end测试用例的一个挑战是避免网络访问。设计到网络访问的测试通常比只访问本地资源的测试要慢,并且访问远程服务也会因为不可决定性以及远程服务的不可用导致脆弱

Hermetic Server

在Google设计end-to-end测试的一个技巧是Hermetic Servers
什么是Hermetic Server呢?简单说就是”server in a box”。如果你可以将整个服务在一台无网络连接的机器上启动起来并保证其正常工作,那么你就拥有一个hermetic server了。广义的hermetic定义中只要是一套隔离的系统即可,本文是广义hermetic的一个特例。
为什么hermetic server是有用的呢?因为,如果你的整个SUT是由一系列的hermetic server组合而成的,那么该SUT就可以在一台机器上启动起来,直接测试;没有网络连接的必要!这个单机可以是一台物理机也可以是一台虚拟机。

设计Hermetic Servers

构建hermetic server的过程,起始于一个新服务设计阶段的早期。有一下几点值得关注:

  • 所有指向其他服务的连接,都需要再运行时以一种DI的形式注入进去,比如命令行参数。
  • 所有静态文件都被打包进了该server的二进制包里。
  • 如果服务需要访问远程存储,保证该远程存储可以用数据文件或内存实现替换掉。

满足上述需求,会使我们拥有一个高度可配置的服务,该服务也有潜力成为一个hermetic server。但广有这些特点还不够。我们需要如下完成如下几项,才能真的完成一个hermetic server:

  • 保证那些我们的测试用例不会使用的连接点,都有相应的fake实现,以确保最终我们能验证“确实没有进行交互”。
  • 提供一些工具来帮助快速灌入测试数据。
  • 提供日志工具,在请求/响应经过SUT时,trace下这些 请求/相应。

在测试中使用Hermetic Servers

让我们把上面展示过的SUT拿过来,并假设所有涉及的服务都是hermetic server。
下面是一个用户请求的end-to-end测试用例,画出来的样子:

SUT-2

该end-to-end测试做了如下几步:

  • 在一个单机上启动图中所示的整个SUT
  • 通过测试客户端想服务发送请求
  • 验证服务的响应
    一个值得注意的点是图中指向mock server连接在这个测试中是是没有必要的。如果我们想要验证这个服务,那么我们也需要提供一个对应的hermetic server。
    这个end-to-end测试更可靠,主因是TA没有使用网络连接。TA也更快,因为所有数据都在内存里或是本地磁盘里。我们可以在持续构建中跑这些而是用例,因此可以保证图中服务的任何一个发生变更时都可以执行该测试。如果测试失败了,日志模块会帮助找到问题发生在哪里。
    我们在大量的end-to-end测试中使用了hermetic server。一些比较典型的例子如下:
  • 启动测试,用以验证没有DI错误
  • 后端服务的API测试
  • 微缩benchmark性能测试
  • 前端的UI及API测试

结论

Hermetic server也有他自己的弊端。他们会导致测试的执行时间变长,因为其需要在你执行end-to-end测试时把整个SUT都启动起来。如果你的测试限制了CPU和内存资源,那么可能由于服务间复杂交互的提升hermetic server可能会导致你最终超限。你可以在内存存储中使用的数据集大小也远小于在生产环境的存储中的大小。
Hermetic server是一种非常有意义的测试工具。像所有其他工具一样,TA也需要被斟酌着用在那些合适的地方。

参考文献

https://testing.googleblog.com/2012/10/hermetic-servers.html