系列10-接口/UI 自动化怎么验落库?数据工厂与数据库断言实践
接口返回 "code":0、UI 提示「提交成功」,数据库里却没有记录------这种 bug JSON 断言抓不到。
纯 httpx / Postman 方案里,测开往往 手写 pymysql 脚本 做 setup/teardown;用例一多,脚本复制粘贴、连接信息散落、清理不干净 污染环境。
数据工厂 把「连库、跑 SQL、断言、清理」收进平台,接口套件和 UI 步骤 都能用。
一、为什么需要库断言
| 场景 | 仅 JSON 断言 | + 库断言 |
|---|---|---|
| 创建订单 API | 返回 id | orders 表真有行、状态=待支付 |
| UI 提交表单 | toast 成功 | user_profile 字段更新 |
| 删除接口 | 200 | 软删除 flag=1 |
| 并发重复提交 | 200 | 唯一索引未重复 |
二、数据工厂能力一览
| 能力 | 说明 |
|---|---|
| 环境级数据源 | MySQL / PostgreSQL / Redis,按项目+环境隔离 |
| SQL 模板 | setup(造数)/ teardown(清数)/ query(查询) |
| 变量替换 | SQL 中 ${``{order_id}} 与接口变量同源 |
| 套件 Hooks | 套件执行前后自动跑 SQL |
| 接口库断言 | 用例/套件级只读校验 |
| UI 步骤「数据库断言」 | 点击提交后插一步查库 |
| 密码加密 | Fernet 存密文,接口不回显明文 |
路径:接口自动化 → 数据工厂。
三、配置数据源(Docker 注意)
- 新建数据源,绑定 环境(创建后不可改环境)
- 类型 MySQL / PostgreSQL / Redis
- 填写 host、port、库名、用户、密码
- 测试连接 → 保存(只测不存会导致列表再测失败)
Docker 部署坑 :Backend 容器内连 MySQL,host 填 mysql (compose 服务名),不是 127.0.0.1。
| 类型 | 默认端口 |
|---|---|
| MySQL | 3306 |
| PostgreSQL | 5432 |
| Redis | 6379(DB Index 如 0) |
勾选 允许写操作 才能跑 setup/teardown 写 SQL。
四、SQL 模板示例
setup:插入测试用户
sql
INSERT INTO users (username, status) VALUES ('auto_${{run_id}}', 1);
teardown:清理
sql
DELETE FROM orders WHERE user_id = ${{user_id}};
DELETE FROM users WHERE username LIKE 'auto_%';
query 断言:订单状态
sql
SELECT status FROM orders WHERE id = ${{order_id}} LIMIT 1;
-- 断言:status = 'PAID'
五、接口套件 Hooks
setup_sql_ids → 套件开始前造数
执行用例 1..N
teardown_sql_ids → 套件结束后清数
db_assertions → 套件级库断言(全部用例跑完或按设计触发)
与 stop_on_failure 配合:前置 setup 失败则不跑用例,避免脏数据。
5.1 源码视角:setup/teardown 在何时执行
接口套件走 backend/app/core/api_suite_runner.py 的 execute_api_suite_cases:
python
merged = await merge_exec_variables(env, project_global_vars, accumulated_vars)
setup_hooks = await run_suite_hooks(suite, env.id, merged, setup=True)
# ... 跑用例 ...
teardown_hooks = await run_suite_hooks(suite, env.id, accumulated_vars, setup=False)
run_suite_hooks 内部调 run_sql_templates_by_ids(db_factory_service.py):
python
async def run_sql_templates_by_ids(template_ids, variables, env_id, project_id, *, phase="setup"):
extracted_vars = dict(variables or {})
for tpl_id in template_ids or []:
exec_result = await execute_sql_on_datasource(ds, tpl.sql_text, extracted_vars, ...)
# SQL 里 ${{order_id}} 与接口变量同一套替换规则
return {"success": success, "logs": logs, "variables": extracted_vars}
变量同源 :接口用例 extract 的 order_id 进入 accumulated_vars 后,setup/teardown SQL 里的 ${``{order_id}} 会被同一替换层解析------不必像 Postman 那样在 Tests 里再写一遍 pm.environment.set 给 SQL 脚本用。
UI 套件则不同:Backend 发 MQ 前 跑 setup;teardown / 步骤级库断言在 Runner 完成后回调 POST .../data-factory/internal/ui-suite-hooks,Runner 不持有业务库密码(connect 模式安全边界)。
六、UI 步骤中的数据库断言(差异化)
UI 流程:填写表单 → 点击提交 → 【数据库断言步骤】→ 继续或结束
在步骤 JSON 中选择关键字 数据库断言 ,配置 SQL + 期望行数/字段值,无需另写脚本。
适合:UI 点完看库,比 UI 上找 toast 更可靠。
步骤 JSON 概念示例(关键字「数据库断言」,与 Runner kw_db_assert 参数一致):
json
{
"keyword": "数据库断言",
"method": "kw_db_assert",
"params": {
"datasource_id": 1,
"sql": "SELECT status FROM orders WHERE id = ${{order_id}} LIMIT 1",
"field": "status",
"operator": "equals",
"expected": "PAID"
},
"desc": "校验订单状态已落库"
}
Runner 不直连业务库 ,步骤执行时 POST Backend /data-factory/internal/evaluate-assertion,由平台用环境数据源跑 SQL。
七、实操:下单后验 orders 表
- 数据工厂:配置测试环境 MySQL 数据源
- 新建 SQL 模板 query:
SELECT count(*) AS cnt FROM orders WHERE id=${``{order_id}} - 接口用例「创建订单」extract
order_id - 同套件加 库断言 :
cnt = 1 - 套件 teardown 删除测试订单
- 执行计划,失败看断言明细
八、污染控制与权限
| 实践 | 说明 |
|---|---|
| 专用测试库/schema | 勿连生产 |
| teardown 必配 | 即使失败也尽量清(可套件级 finally) |
auto_${``{run_id}} 前缀 |
便于批量清理 |
| 角色权限 | data_factory:view / edit 分离 |
| 只读账号 | 纯断言环境用只读 DB 用户(写操作另配) |
九、小结
- JSON 断言验接口,库断言验落库。
- SQL 模板 + 变量 与接口变量池统一。
- setup/teardown 解决造数与清理;UI 也可插库断言步骤。
- Docker 内 host 用 服务名,密码测完记得点保存。
附录 A:源码文件索引(进阶读码)
正文 §5.1 已讲 hooks 触发时机;完整链路:
| 顺序 | 文件 | 关注点 |
|---|---|---|
| 1 | core/db_factory_service.py |
run_sql_templates_by_ids、evaluate_db_assertions |
| 2 | routers/http/data_factory.py |
数据源 CRUD、UI hooks 内部 API |
| 3 | core/api_suite_runner.py |
run_suite_hooks、setup/teardown |
| 4 | runner/tools/db_assert_client.py |
UI 步骤库断言 HTTP 调用 |
安全边界 :connect 模式 Runner 无 DB 密码;SQL 在 Backend 执行。for_assertion=True 时强制只读,即使数据源勾了写操作。
Docker 坑 :Backend 容器内 host=mysql;Runner 在宿主机则 127.0.0.1:3306------同一环境不要混两种部署。
关于 BrickCore
| 项 | 链接 |
|---|---|
| 源码 | https://gitee.com/BanZhuanKeOrz/BrickCore |
| 在线体验 | http://43.142.83.156/ |
| 数据工厂文档 | http://43.142.83.156/showcase/docs/ |
支持与交流
- 觉得有用欢迎 Star ⭐
- 问题反馈:Gitee Issues 或评论区留言