Files
Neo-ZQYY/tests/test_property_test_db_consistency.py
Neo 2a7a5d68aa feat: 2026-04-15~04-20 累积变更基线 — 多主线合流
主线 1: rns1-customer-coach-api + 04-miniapp-core-business 后端实施
  - 新增 GET /xcx/coaches/{id}/banner 轻量接口
  - performance/records 加 coach_id 参数 + view_board_coach 权限分流
  - coach/customer/performance/board/task 服务层重构
  - fdw_queries 结算单粒度聚合 + consumption_summary 视图统一
  - task_generator 回访宽限 72h + UPSERT 替代策略 + Step 5 保底清理
  - recall_detector settle_type=3 双重限制 + 门店级 resolved

主线 2: 小程序权限分流 + 新增 coach-service-records 管理者视角业绩明细页
  - perf-progress 共享模块去重 task-list/coach-detail 动画逻辑
  - isScattered 散客标记端到端
  - foodDetail/phoneFull/creator* 字段透传

主线 3: P19 指数回测框架 Phase 1+2
  - 3 个指数表 stat_date 日快照模式
  - 新增 DWS_INDEX_BACKFILL / DWS_TASK_SIMULATION 工具任务
  - task_engine 升级 HTTP 实时 + 推演回测双模式

主线 4: Core 维度层启用
  - 新增 CORE_DIM_SYNC 任务(DWD → core 4 维度表)
  - 修复 app 视图空查询问题

主线 5: member_project_tag 改为 LAST_30_VISITS 消费次数窗口

主线 6: 2 个迁移 SQL 已执行(stat_date + member_project_tag 新窗口)
  - schema 基线与 DDL 快照同步

主线 7: 开发机路径迁移 C:\NeoZQYY → C:\Project\NeoZQYY(约 95% 改动量)

附带: 新建运维脚本(churned_customer_report / simulate_historical_tasks /
      backfill_index_snapshots)+ tools/task-analysis/ 任务分析工具

合计 157 文件。未包含中间产物(tmp/ .playwright-mcp/ inspect-* excel/sheet 分析 txt)。
审计记录见下一个 commit。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 06:32:07 +08:00

105 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
测试数据库结构一致性属性测试
**Validates: Requirements 9.1, 9.2**
Property 8: 对于任意生产数据库etl_feiqiu、zqyy_app中的 schema 和表定义,
对应的测试数据库test_etl_feiqiu、test_zqyy_app中应存在相同的 schema 和表结构。
测试逻辑:测试数据库创建脚本通过 \\i 引用生产 DDL 文件,
结构一致性可以通过验证脚本引用的完整性来保证——
即每个 \\i 引用的 DDL 文件在磁盘上实际存在。
"""
import os
import re
from hypothesis import given, settings
from hypothesis.strategies import sampled_from
# ── 路径常量 ──────────────────────────────────────────────
MONOREPO_ROOT = r"C:\Project\NeoZQYY"
DB_CONFIGS = {
"etl_feiqiu": {
"script": os.path.join(
MONOREPO_ROOT, "db", "etl_feiqiu", "scripts", "create_test_db.sql"
),
"base_dir": os.path.join(
MONOREPO_ROOT, "db", "etl_feiqiu", "scripts"
),
},
"zqyy_app": {
"script": os.path.join(
MONOREPO_ROOT, "db", "zqyy_app", "scripts", "create_test_db.sql"
),
"base_dir": os.path.join(
MONOREPO_ROOT, "db", "zqyy_app", "scripts"
),
},
}
# ── 解析 \\i 引用 ─────────────────────────────────────────
# 匹配注释中的 \i 指令psql 元命令),如:
# \i ../schemas/meta.sql
# \i ../seeds/*.sql ← 通配符引用,跳过
_PSQL_INCLUDE_RE = re.compile(r"\\i\s+(\S+)")
def _extract_ddl_refs(script_path: str, base_dir: str) -> list[tuple[str, str]]:
"""
从 create_test_db.sql 中提取所有 \\i 引用的 DDL 文件路径。
返回 [(相对路径, 绝对路径), ...] 列表。
跳过包含通配符的引用(如 ../seeds/*.sql
"""
with open(script_path, encoding="utf-8") as f:
content = f.read()
refs = []
for m in _PSQL_INCLUDE_RE.finditer(content):
rel_path = m.group(1)
# 跳过通配符引用,无法逐文件验证
if "*" in rel_path:
continue
abs_path = os.path.normpath(os.path.join(base_dir, rel_path))
refs.append((rel_path, abs_path))
return refs
# ── 预加载所有引用(模块级,只解析一次) ─────────────────────
DDL_REFERENCES: list[tuple[str, str, str]] = []
"""每个元素: (数据库名, 相对路径, 绝对路径)"""
for db_name, cfg in DB_CONFIGS.items():
assert os.path.isfile(cfg["script"]), (
f"测试数据库创建脚本不存在: {cfg['script']}"
)
for rel_path, abs_path in _extract_ddl_refs(cfg["script"], cfg["base_dir"]):
DDL_REFERENCES.append((db_name, rel_path, abs_path))
assert len(DDL_REFERENCES) > 0, (
"未从 create_test_db.sql 中提取到任何 \\i DDL 引用,请检查脚本内容"
)
# ── 属性测试 ──────────────────────────────────────────────
@given(ref=sampled_from(DDL_REFERENCES))
@settings(max_examples=100)
def test_test_db_ddl_references_exist(ref: tuple[str, str, str]):
"""
Property 8: 测试数据库结构一致性
对于任意生产数据库的测试数据库创建脚本中 \\i 引用的 DDL 文件,
该文件在磁盘上应实际存在。这保证了测试数据库能完整复用生产 DDL
从而确保结构一致性。
**Validates: Requirements 9.1, 9.2**
"""
db_name, rel_path, abs_path = ref
assert os.path.isfile(abs_path), (
f"[{db_name}] create_test_db.sql 引用的 DDL 文件不存在: "
f"{rel_path}{abs_path}"
)