跳转到内容
AsterDrive Developer Docs开发者

测试与数据库后端

本文描述的是当前仓库已经落地的测试后端切换机制,不是未来规划。

  • 默认集成测试仍然跑内存 SQLite
  • 现在可以通过 ASTER_TEST_DATABASE_BACKENDtests/common/mod.rs 里的通用 common::setup() 切到 PostgreSQL 或 MySQL
  • PostgreSQL / MySQL 不是要求你手填数据库 URL;测试会自动用 testcontainers 起容器
  • 为了支持并行测试,PostgreSQL / MySQL 下每个测试实例都会分配独立数据库,不共用同一个 schema

支持三个值:

  • sqlite
  • postgres
  • mysql

未设置时等价于:

Terminal window
ASTER_TEST_DATABASE_BACKEND=sqlite

集成测试按产品域组织为 Cargo test target:

  • auth:认证、MFA、外部认证和用户账号
  • files:文件、目录、上传、元数据、搜索和回收站
  • sharing:分享、团队和公开访问
  • storage:存储驱动、策略、远端节点和迁移
  • operations:管理、审计、CLI、维护、邮件和任务
  • platform:数据库、缓存、中间件、配置和结构契约
  • webdav / wopi:协议集成测试
  • multi_primary:需要 multi-primary-e2e feature 的多 Primary E2E

使用 cargo nextest run --test <target> <module>:: 缩小默认 SQLite 测试范围,例如 cargo nextest run --test files search::

默认 SQLite:

Terminal window
cargo nextest run

PostgreSQL / MySQL 使用专用的 database profile。它保持 nextest 的 process-per-test 隔离,并为数据库初始化和异常回收提供更长的慢测试诊断窗口。

切到 PostgreSQL:

Terminal window
ASTER_TEST_DATABASE_BACKEND=postgres cargo nextest run --profile database

切到 MySQL:

Terminal window
ASTER_TEST_DATABASE_BACKEND=mysql cargo nextest run --profile database

如果你只想复现某一组用例,和平时一样筛测试名即可:

Terminal window
ASTER_TEST_DATABASE_BACKEND=postgres cargo nextest run --profile database --test files search::test_search_by_name
ASTER_TEST_DATABASE_BACKEND=mysql cargo nextest run --profile database --test operations admin::test_admin_team_crud

需要复用已经运行的外部 MySQL 数据库时,可把 ASTER_TEST_MYSQL_DATABASE_URL 指向专用测试库;若该库不是 testcontainers 管理的 schema-template 容器,同时设置 ASTER_TEST_DISABLE_MYSQL_SCHEMA_TEMPLATE=1,测试会直接在该库完成 migration 和验收。该开关只用于一次性的外部测试库,不要指向含有产品数据的实例。

tests/common/mod.rs 里的 common::setup() 会按下面的规则工作:

  1. 读取 ASTER_TEST_DATABASE_BACKEND
  2. 如果是 sqlite,直接返回内存 SQLite 的 AppState
  3. 如果是 postgresmysql,通过 testcontainers 启动一个共享容器
  4. 在 suite 级跨进程锁下验证 migration fingerprint;失效时只重建一次迁移完成的 PostgreSQL template database 或 MySQL schema template
  5. PostgreSQL 从 template clone 独立数据库;MySQL 从内存中的 DDL 与 migration history snapshot 构建独立 schema
  6. 在独立数据库中初始化默认策略和运行时配置,再返回 AppState

这意味着:

  • PostgreSQL / MySQL 共享容器会尽量跨多次本地测试命令复用,不会每次都重新冷启动
  • 但数据库实例不会复用,所以并行集成测试不会互相污染数据
  • 同一个 nextest run 内已经退出的进程资源会按 NEXTEST_RUN_ID 延迟保留,避免 MySQL 同时创建和删除大量表;下一次 run 启动时会确定性回收
  • 使用容器内的 postgres 管理账号启动基础库
  • suite 只迁移一次 template database,每个测试实例由管理连接执行 CREATE DATABASE ... TEMPLATE ...
  • 业务测试连接直接使用对应的测试数据库
  • 业务测试默认仍使用容器内的 aster 用户
  • 独立数据库仍由 root 连接创建
  • 普通测试用户的访问权限会在容器启动时一次性补齐,不再为每个测试库单独跑一次 GRANT
  • migration 只在 suite template 上执行一次;每个测试进程读取 DDL 和 migration history snapshot 后立即释放 fixture 锁,再并行构建自己的 schema
  • reusable container 会按 endpoint identity 配置 table_definition_cachemax_connections;配置契约变化时会重新探测并更新容器

下面这些情况,别只拿 SQLite 自我安慰:

  • 你刚改了 repo 层查询,而且里面有数据库分支逻辑
  • 你刚改了全文搜索、索引、分页、排序、大小写匹配
  • 你怀疑某段 SQL / SeaORM builder 在 PostgreSQL 或 MySQL 上行为不一致
  • 你要修的是“SQLite 绿,生产库炸”的问题

更实际一点的建议:

  • 先用默认 SQLite 快速迭代
  • 改到数据库相关逻辑后,至少再补跑一次 postgres
  • 如果代码里还有 MySQL 分支,再补跑一次 mysql

仓库里还有 tests/platform/database_backends.rs,它的定位没有变:

  • 主要负责生产数据库相关的 smoke coverage
  • 会显式验证 PostgreSQL / MySQL 搜索索引、搜索链路和跨库迁移路径
  • 它是专门的后端 smoke 覆盖,不是唯一会跑多数据库的测试入口;普通集成测试只要走 common::setup(),也可以用 ASTER_TEST_DATABASE_BACKEND 切后端

新的 ASTER_TEST_DATABASE_BACKEND 机制解决的是另一件事:

  • 让原本默认写成 common::setup() 的大部分集成测试,可以在不改测试主体的情况下切到其他后端复跑
  • PostgreSQL / MySQL 依赖本机可用的 Docker / 容器运行时
  • 第一次跑会拉镜像,明显比 SQLite 慢
  • 之后同一个工作区重复跑 postgres / mysql 测试,通常会直接复用已有共享容器,冷启动开销会小很多
  • 如果某个测试没有走 common::setup(),而是自己手写数据库初始化逻辑,那它不会自动吃到这个开关
  • common::setup_with_database_url(...) 仍然保留给需要显式控制数据库地址的场景,它不会替你解读 ASTER_TEST_DATABASE_BACKEND

如果你怀疑测试没有按预期切后端,优先看三件事:

  1. 当前用例是不是走的 common::setup()
  2. shell 里是否真的导出了 ASTER_TEST_DATABASE_BACKEND
  3. 本机 Docker 是否可用,以及对应镜像能否拉起

SFTP 驱动有单独的集成测试:

Terminal window
cargo nextest run --test storage sftp::

这个测试默认会通过 testcontainers 启动 lscr.io/linuxserver/openssh-server 容器,完成一次真实上传、下载、range 读取、删除和主机密钥指纹确认流程。它需要本机 Docker / 容器运行时可用。

如果当前环境不能跑 Docker,可以显式关闭:

Terminal window
ASTER_SFTP_TEST_DOCKER=0 cargo nextest run --test storage sftp::

关闭后测试会跳过容器 round-trip。不要把这个变量作为默认 CI 行为;SFTP 是真实存储驱动,PR 改到驱动、connector、descriptor 或上传下载链路时应优先保留默认 Docker 测试。

src/storage/drivers/sftp.rs 里还有一个手动真实服务器用例,需要 ASTER_SFTP_TEST_*ASTER_SFTP_TEST_HOST_KEY_FINGERPRINT。它不替代 tests/storage/sftp.rs 的默认 Docker 覆盖,主要用于排查特定 SFTP 服务器兼容性。