PostgreSQL 的测试体系是开源数据库中最严谨、最全面、最工程化的典范之一。它不仅覆盖功能正确性,还深入到并发、崩溃恢复、跨平台兼容性等生产级场景。下面从测试架构、类型、工具、流程和最佳实践五个维度详细解析。


一、整体测试架构:分层 + 多维覆盖

PostgreSQL 的测试不是单一工具,而是一个多层次、多目标的生态系统:

+----------------------------+
|      开发者本地测试         |
|  (make check / make installcheck) |
+----------------------------+
            ↓
+----------------------------+
|     官方 BuildFarm CI       |
|  (全球 100+ 台机器持续运行)   |
+----------------------------+
            ↓
+----------------------------+
|    社区模糊测试 & 安全审计   |
|  (如 oss-fuzz, SQLancer)    |
+----------------------------+

所有测试代码位于源码树的 src/test/ 目录下。


二、核心测试类型详解

1. 回归测试(Regression Tests) —— 功能正确性的基石

  • 位置src/test/regress/
  • 原理
    • 执行 SQL 脚本(.sql 文件)
    • 将输出与预期结果(.out 文件)逐行比对
    • 若不一致,视为回归错误(regression)
  • 示例
    -- tests/regress/sql/select.sql
    SELECT 1 + 1;
    
    对应的预期输出:
    -- tests/regress/expected/select.out
     ?column?
    ----------
            2
    (1 row)
    
  • 特点
    • 覆盖 SQL 标准语法、函数、类型、索引、事务
    • 支持 条件跳过(如 -- @exclude_schema pg_catalog
    • 自动处理 浮点精度差异、时区、locale 等环境变量

运行命令:make installcheck(需已安装 PostgreSQL)


2. 隔离测试(Isolation Tests) —— 并发与事务正确性

  • 位置src/test/isolation/
  • 解决的问题:验证 MVCC(多版本并发控制)在并发读写下的行为是否符合 ANSI SQL 隔离级别(如 READ COMMITTED, SERIALIZABLE)
  • 原理
    • 使用专用 DSL 描述多个会话的交错操作
    • 自动验证最终状态是否符合预期
  • 示例 DSL
    setup
      CREATE TABLE t (a int);
      INSERT INTO t VALUES (1);
    session s1
      BEGIN ISOLATION LEVEL SERIALIZABLE;
      SELECT * FROM t;
    session s2
      BEGIN;
      UPDATE t SET a = 2;
      COMMIT;
    session s1
      SELECT * FROM t;
      COMMIT;
    permutate s1, s2  -- 测试所有可能的执行顺序
    
  • 输出:列出哪些执行顺序会导致串行化失败(符合预期)

这是 PostgreSQL 区别于多数数据库的独特测试能力。


3. TAP 测试(Test Anything Protocol) —— 结构化测试框架

  • 位置src/test/modules/src/test/perl/
  • 用途:测试无法用 SQL 表达的功能,如:
    • 复制(Replication)
    • WAL(Write-Ahead Logging)
    • 后台进程(autovacuum, bgwriter)
    • 扩展(Extensions)
  • 技术栈:Perl + Python 脚本,使用标准 TAP 协议输出
  • 示例输出
    ok 1 - server started
    ok 2 - replication slot created
    not ok 3 - unexpected WAL record type
    
  • 优势:可被任何 TAP 解析器(如 prove)集成到 CI

4. 性能回归测试(pgbench + 自定义基准)

  • 工具:内置 pgbench(TPC-B 模拟)
  • 做法
    • 在每次提交前后运行相同负载
    • 对比 TPS(Transactions Per Second)
    • 超过阈值则告警
  • 扩展:社区使用 pgTAP 编写 SQL 级性能断言

三、关键测试工具链

工具 作用 技术细节
pg_regress 回归测试驱动程序 C 编写,管理临时实例、端口、清理
isolationtester 隔离测试执行器 解析 .spec 文件,生成交错会话
prove TAP 测试运行器 Perl 标准工具,支持并行、超时
BuildFarm 分布式 CI 系统 全球志愿者提供机器,覆盖:
• OS: Linux, Windows, macOS, BSD
• 编译器: GCC, Clang, MSVC
• 配置: debug, optimized, ICU, LDAP
Valgrind / ASan 内存错误检测 在测试中启用,捕获 use-after-free、内存泄漏

四、故障注入与鲁棒性测试

PostgreSQL 不仅测“正常路径”,更重视异常路径

1. WAL 崩溃恢复测试

  • 步骤:
    1. 启动数据库,执行大量写入
    2. 强制 kill -9(模拟断电)
    3. 重启,验证数据一致性
  • 自动化:通过 src/test/recovery/ 中的 Perl 脚本实现

2. 磁盘满模拟

  • 使用 posix_fallocate() 或挂载小容量 tmpfs
  • 验证 PostgreSQL 是否优雅报错而非崩溃

3. 网络分区测试(用于逻辑复制)

  • 使用 iptables 或 tc 模拟网络延迟/丢包
  • 验证复制槽(replication slot)是否阻塞或丢失数据

五、开发者工作流:如何写测试?

场景:为新函数 my_upper(text) 添加测试

  1. 编写 SQL 测试

    -- src/test/regress/sql/my_upper.sql
    SELECT my_upper('hello');
    SELECT my_upper(NULL);
    
  2. 生成预期输出

    # 首次运行,生成 .out 文件
    make installcheck EXTRA_REGRESS_OPTS="my_upper"
    cp results/my_upper.out expected/my_upper.out
    
  3. 验证测试通过

    make installcheck  # 应显示 "my_upper ... ok"
    
  4. 提交 PR:测试文件必须随代码一起提交!

规则:任何功能变更必须附带回归测试,否则不会被合并。


六、BuildFarm:全球分布式 CI

  • 规模:100+ 台机器(由社区志愿者维护)
  • 覆盖维度
    维度 示例
    操作系统 Ubuntu 22.04, Windows Server 2022, FreeBSD 13
    CPU 架构 x86_64, ARM64, PowerPC
    编译选项 --enable-debug--with-ldap--with-icu
    特殊配置 32-bit, valgrind, cassert(断言开启)
  • 结果公开https://buildfarm.postgresql.org
  • 价值:确保提交不会破坏任何平台的构建或测试

七、模糊测试(Fuzzing)与安全测试

虽然 PostgreSQL 核心团队不直接维护 fuzzers,但社区广泛使用:

  • SQLancer
    自动生成语义正确的 SQL,验证优化器与执行器一致性(发现过多个严重 bug)
  • oss-fuzz(Google):
    对 libpq(客户端库)、WAL 解析器进行覆盖率引导模糊测试
  • 自定义 AFL
    社区成员对查询解析器进行 fuzzing

八、为什么 PostgreSQL 测试如此成功?

原则 实践体现
测试即规范 每个 SQL 特性都有对应测试用例
零容忍回归 任何测试失败都会阻塞合并
生产级思维 测试包含崩溃、断电、磁盘满等真实故障
社区共建 BuildFarm 依赖全球志愿者
简单可靠 回归测试基于文本比对,无需复杂断言库

九、学习资源

  1. 官方文档
    PostgreSQL Regression Tests
  2. 源码目录
    src/test/
  3. BuildFarm 实时状态
    https://buildfarm.postgresql.org
  4. 社区工具
    • pgTAP(SQL 级单元测试)
    • SQLancer(自动化 SQL 生成)

总结

PostgreSQL 的测试哲学是:“如果它没被测试,它就不存在。”
通过回归测试 + 隔离测试 + 全球 CI + 故障注入的组合拳,它实现了:

  • 功能正确性(SQL 标准兼容)
  • 并发正确性(MVCC 无 bug)
  • 生产鲁棒性(崩溃后数据不损坏)
  • 跨平台稳定性(从手机到大型机)

这种工程纪律性,正是 PostgreSQL 能成为企业级数据库核心的原因。对于任何严肃的系统软件项目,PostgreSQL 的测试体系都值得深度借鉴。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐