bigywater.tech
Flask · 155

测试数据库事务

测试里怎么让数据库每个用例都是干净的?drop_all、TRUNCATE、事务回滚各有多快?应用代码里的 commit 会不会破坏回滚?这篇用真实的 PostgreSQL 与 pytest 把三种做法的隔离与耗时量出来。

2 passed
三种清理策略下两个有依赖关系的测试的结果(不清理时是 1 failed)
0.77 → 0.59 秒
100 个测试:drop_all 加 create_all 与保存点回滚的总耗时
0 行
保存点方案下,应用代码 commit 之后数据库里实际留下的行数

四种策略的隔离

实测 · 本机执行输出
  不清理                                1 failed, 1 passed in 0.09s
  每个测试 drop_all + create_all         2 passed in 0.08s
  每个测试之后 TRUNCATE                    2 passed in 0.08s
  外层事务 + 保存点,测试结束回滚                  2 passed in 0.07s

上一篇:Fixture 与测试应用工厂;下一篇:测试 Session。

耗时对比

实测 · 本机执行输出
  每个测试 drop_all + create_all         100 passed in 0.43s | 总耗时 0.77 秒
  每个测试之后 TRUNCATE                    100 passed in 0.35s | 总耗时 0.70 秒
  外层事务 + 保存点回滚                       100 passed in 0.25s | 总耗时 0.59 秒

保存点方案

实测 · 本机执行输出
  测试里应用代码 commit 过之后,数据库里实际留下的行数: 0

数据库是自己起的 PostgreSQL(非默认端口)。

分步演示

测试数据库事务
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.7 / Flask 3.1.3 / Werkzeug 3.1.9 / Jinja2 3.1.6 / SQLAlchemy 2.1.1 / gunicorn 26.2.0(都装在自己的虚拟环境里);大多数实验用 Flask 的 test_client(直接调用 WSGI 应用,不经过网络),需要真实 HTTP 时另起 gunicorn 或开发服务器(端口 9600 以上,本机 127.0.0.1);计时用 time.perf_counter,数字每次运行会有小幅抖动。Flask-SQLAlchemy 3.1.1、SQLAlchemy 2.1.1、psycopg 3.3.6、pytest 9.1.1
    • 没有验证:数据库不在本机时的耗时差别、多线程或多进程访问同一个数据库的测试(回滚方案只对同一个连接可见)、pytest-xdist 并行、迁移(Alembic)在测试库上的创建方式、测试里用到真实 commit 的场景(如测试 after-commit 钩子)
    京ICP备2026067502号-1京公网安备11010502063487号