Files
social-app/docs/plans/PLAN-test-db-isolation-2026-02-05.md
qzl ad06fe7de4 refactor: align backend layout and supabase infra
Consolidate backend modules/tests under the backend package while syncing Supabase compose/env config and related plans.
2026-02-05 15:13:06 +08:00

4.6 KiB

测试数据隔离方案(Supabase + Python 后端)

背景现状

  • 后端在 backend/src/core/config/settings.py 使用 SOCIAL_DATABASE__* 生成 database_url
  • 本地 Supabase 通过 supabase-db 容器提供 Postgres,宿主端口由 SOCIAL_DATABASE__PORT 控制(默认映射到容器 5432)。
  • 注意:supabase-pooler 的 5432 仅用于连接池;测试与迁移应直连 supabase-db 的宿主端口。
  • 单元数据库测试目前使用 SQLite 内存库(见 tests/unit/database/*),不影响开发库。
  • 真实 Postgres 的集成/E2E 当前未统一隔离策略;当开始接入真实 DB 时,需要按本文方案隔离与清理。

目标

  • 测试过程不污染开发数据。
  • 测试可重复、可并行、可在本地与 CI 稳定运行。
  • 变更成本可控,优先在现有架构上落地。

结论(适配本项目)

采用“事务回滚 + 独立测试数据库”的混合策略:

  • 默认测试使用事务回滚,快速、零污染(适用于单连接/单事务场景)。
  • 需要真实提交、并发或触发器行为的测试使用独立测试数据库。

方案设计

A. 事务回滚(默认)

适用:单元测试、绝大多数集成测试(当这些测试连接真实 Postgres 时)。

核心思路:

  • 每个测试在事务中运行。
  • 测试结束自动回滚。

优点:

  • 速度快,无需新增数据库。
  • 测试间完全隔离。

限制:

  • 无法验证真实 COMMIT 结果。
  • 并发、多连接事务隔离测试不准确。

B. 独立测试数据库(E2E/并发)

适用:E2E、并发、触发器、LISTEN/NOTIFY 等需要真实提交的场景。

核心思路:

  • 在现有 Supabase Postgres 实例中创建独立数据库。
  • 测试使用专用 SOCIAL_DATABASE__NAME 连接,端口/账号/密码来自 SOCIAL_DATABASE__*
  • 测试前应用迁移,测试后清理。

优点:

  • 行为最接近真实环境。
  • 与开发数据完全隔离。

成本:

  • 需要迁移与清理策略。

与现有测试模块的衔接

  • tests/unit/database/* 已使用 SQLite 内存库,无需改造。
  • 未来若 tests/integration/*tests/e2e/* 连接真实 Postgres,应切换到本文的测试库策略。
  • 使用 SOCIAL_DATABASE__NAME=postgres_test 启动测试,以避免污染开发库。

实施步骤(与项目当前结构对齐)

1) 创建独立测试数据库

在本地 Supabase 容器中创建测试库:

docker exec -e PGPASSWORD="$SOCIAL_DATABASE__PASSWORD" supabase-db \
  psql -U "$SOCIAL_DATABASE__USER" -c "CREATE DATABASE postgres_test;"

说明:

  • 容器名为 supabase-db(已在 infra/docker 运行)。
  • 数据库名建议 postgres_test,与 .envSOCIAL_DATABASE__NAME=postgres 区分。

2) 运行迁移到测试库

使用测试环境变量指向测试库后,应用 Alembic 迁移:

SOCIAL_RUNTIME__ENVIRONMENT=test \
SOCIAL_DATABASE__NAME=postgres_test \
uv run alembic upgrade head

说明:

  • 执行位置:/home/qzl/Code/social-app/backend
  • 仍使用当前 .env 中的 SOCIAL_DATABASE__HOSTSOCIAL_DATABASE__PORT

3) 事务回滚测试(默认)

测试执行时注入事务回滚机制:

  • 在测试会话层创建单连接事务。
  • 对每个测试用例使用 SAVEPOINT(或嵌套事务)。
  • 测试结束回滚到 SAVEPOINT。

这套策略可保持速度与隔离性,同时不需要额外数据库。

4) 独立测试数据库执行(E2E/并发)

对于需要真实提交的测试,使用测试库运行:

SOCIAL_RUNTIME__ENVIRONMENT=test \
SOCIAL_DATABASE__NAME=postgres_test \
uv run pytest tests/e2e

清理策略(二选一):

  • 小规模测试:TRUNCATE public schema 的业务表(不影响 auth 等系统 schema)。
  • 大规模测试:DROP DATABASE postgres_test; 后重建并迁移。

5) 本地/CI 统一策略

  • 本地默认:事务回滚。
  • CI:独立测试库(保证完全隔离、无隐式依赖)。

风险与规避

  • 不要在清理时操作 authstorage 等 Supabase 系统 schema。
  • E2E 使用独立数据库,避免与开发数据交叉。
  • 迁移必须由 Alembic 统一维护,禁止手动改库。

落地检查清单

  • 已创建 postgres_test 数据库。
  • 测试库迁移已应用。
  • 事务回滚测试已接入(默认路径)。
  • E2E 使用测试库运行。
  • 清理策略执行脚本可复用。

备注

本方案基于当前项目的 Supabase 本地 Docker 结构与后端配置方式(SOCIAL_DATABASE__*)。 无需变更 Supabase 组件,优先在测试层完成隔离与清理。