pgtestdb 模板克隆:PostgreSQL 测试库极速搭建方案
我被提醒了一下杯子彼得·唐斯的存在PGtestDB,一个Go/Postgres测试包。
pgtestdb 是围绕 Postgres 构建的模板数据库,这是一个你可以直接从原版 PSSQL 壳体中试用的内置功能:
CREATE DATABASE dbname TEMPLATE template_to_copy;
复制模板非常快,比从零迁移测试数据库更快,而且非常多比起现在一些项目使用的基于Docker的重型技术,还要多。在底层,Postgres枚举模板的关系,并将它们的实体化堆、索引和目录文件复制成8 kB页面块。
我记得多年前读过这个功能,但说实话我都忘了它的存在,我很好奇它和其他测试方法相比表现如何,于是我用 Codex 把 pgtestdb 拼接到 River 的测试套件里,看看效果如何。
我喜欢认为 River 的测试方法在速度和可靠性方面或多或少是金标准。它使用一套定制的测试辅助工具,基于模式隔离测试用例,这种方法比测试交易,但具有一些优点:
- 保留测试状态以备测试失败时的检查。
- 支持测试数据库范围的功能,如监听/通知。
- 支持围绕多笔交易交互和回滚的测试边缘。
在 Postgres 中,模式比数据库轻,所以基于模式的方法有优势。但你无法克隆模式,所以基于模式的方法每次都必须运行迁移,这给了 pgtestdb 明显的优势。
这应该能给我们一个有趣的对比。以下是我得到的结果:
| 方法 | 伯爵 | 狠 | 第90页 | 第95页 | 马克斯 |
|---|---|---|---|---|---|
| PGTESTDB 克隆 | 466 | 98.4毫秒 | 247.4毫秒 | 299.5毫秒 | 465.1毫秒 |
| Create + migrate schema | 81 | 99.4毫秒 | 152.1毫秒 | 209.0毫秒 | 327.0毫秒 |
我们发现两种方法的时序非常相似,大约是100毫秒的设置时间。
我一直内化到任何涉及新数据库的开发都会相对较慢,所以对pgtestdb在这里的方法速度之快感到惊讶。
鉴于 River 已经很快,测试模式隔离顺便有助于验证 River 的基于模式的配置功能如宣传的那样,但我会在我们的文档中添加一个推荐,特别是针对那些想要端到端测试的用户(即由客户插入的作业→由工人完全完成)。
我刚才在上面沙袋里。虽然搭建时间基于模式的方法类似于PGTESTDB的完整数据库,总体而言,测试套件在前者上运行速度快约3.5倍:
| 方法 | 墙时 |
|---|---|
| PGTESTDB 克隆 | 51.07先令 |
| Create + migrate schema | 14.54秒 |
但这并不是因为模式真的快太多。River 的测试助手有一个有用的优化,就是它们会创建 Go 即时并行化所需的测试模式,但会在测试用例完成时保持它们的池化。
如果一个未被认领的模式已经准备好,测试用例会清理并重用它,而不是从头生成新的。
说起来容易做起来难,因为你需要考虑细节,比如模式版本——也就是说,在跨模式版本测试时,每个测试用例只能在它预期的同一版本上重复使用一个模式。
这当然是可行的,但需要一些思考。我在LLM之前写了River的实现,花了几天时间把所有bug都解决掉。
我提到重用是因为它也可以用 pgtestdb 实现,可能是包的一部分,或者作为调用它的项目的增强。启动测试数据库需要 100 毫秒相当快,但如果你构建一个包含 10,000 个测试的完整应用,理想情况下你希望测试设置速度快大约 10 倍。
重用可以降低到 10-20 毫秒,并且更接近测试事务。