最近,tsnsrv 获得了许多高质量的贡献,增加了对 Headscale 和自定义证书等的更好支持。当事情发生变化时,出现了一些 bug,但现有测试无法捕捉到这些 bug,而是 nixos 模块中的 bug。这是一个研究是否可以测试 tsnsrv NixOS 模块并可能提高整个代码库基线质量的好机会。
如何进行 NixOS 集成测试?
Nix flake 有一个名为checks
的属性集,每个属性集定义一个测试。每个测试都有一组 NixOS 机器的定义(作为虚拟机构建)和一个用类型检查和 linted python 编写的测试脚本。每个机器在 python 脚本中作为一个变量存在,你可以告诉它诸如wait_for_unit
(等待 systemd 单元启动)或get_screen_text
(对虚拟机屏幕上的像素进行 OCR)等事情。对于有经验的程序员来说,这听起来像是典型的端到端/高级集成测试灾难:运行测试的环境可能导致程序交互方式的差异,导致诸如“等待事物超时”等令人愉快的测试失败(稍后会详细介绍)。
为什么它们能起作用?
作者对这些测试能有效运行感到惊讶,认为有以下因素使其效果良好:
- 测试框架构建的机器非常真实,运行真实的 NixOS,定义一个机器很容易。
- 连接这些机器的网络非常真实,机器可以相互看到并有 DNS 条目,防火墙规则也有效。
- 测试驱动程序本身利用了大量 qemu 的功能,如 OCR 文本、模拟插入 USB 驱动器、重启机器等。
- 尽管非常真实,但机器上软件的默认设置是“一切保持运行”,NixOS 有非常合理的默认值并与 systemd 集成良好,若需要偏离默认值也可以。
- 最重要的是,nixos 集成测试套件在 nixpkgs 仓库的许多 pull 请求中得到了锻炼,已经合并了近 25 万个。
一个工作的测试只需约 1 分钟即可完成,作者对此速度感到惊讶。
为 tsnsrv 使其工作
tsnsrv 的 nix 集成是通过nix flake实现的,这是 nix 中的一个相对较新的概念,使用flake.parts,这是一个用于处理 flakes 的相对较新的库,这导致需要大量的试验和错误。幸运的是,找到运行测试的按钮并不难,但需要一些挖掘。包括找到定义runTest
函数的位置(即使有经验的 nix 贡献者也会感到困惑)以及仅在 linux 系统上定义检查等。最终作者有了一个在 linux 机器上不到 50 秒就能完成的集成测试,并可以进行迭代。
然后作者编写了一个测试,包括设置 headscale、tailscale 向 headscale 认证、tsnsrv 向 headscale 认证并设置监听明文 HTTP 的代理,以及尝试访问 tsnsrv 上暴露的站点,测试通过。
但哦不:意外超时
设置好端到端测试后,作者尝试合并一些贡献,但第一个就立即失败了,测试显示“超时”。阅读测试日志后发现,是因为提交的更改改变了明文 HTTP 监听器的逻辑,存在一个||
/ &&
运算符优先级的 bug,导致 tsnsrv 无法正常启动。在设置端到端测试的 2 小时内,它们就捕捉到了一个合法的回归。
总结:作者是粉丝
作者使用 NixOS 集成测试库仅几天,但目前是其巨大的粉丝。这是迄今为止使用过的最愉快(尽管仍有些独特)的端到端测试框架,似乎很容易控制时间/竞争条件错误,最重要的是,已经捕捉到了一个作者几个月都不会发现的 bug。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。