Files
feiqiu-ETL/etl_billiards/scripts/test_presets.py
2025-11-19 05:32:03 +08:00

163 lines
5.9 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 -*-
"""测试命令仓库:集中维护 run_tests.py 的常用组合,并支持一键执行。
参数键说明(可在 PRESETS 中任意叠加):
1. suite
类型:列表;值:["online"], ["offline"], ["integration"] 等。
含义:引用 run_tests 内置测试套件。online=在线模式offline=离线模式integration=数据库集成测试。
用法:["online","offline"] 表示一次执行两套;["integration"] 仅跑数据库相关用例。
2. tests
类型:列表;示例:["tests/unit/test_config.py"]。
含义:自定义的 pytest 目标路径,适合补充临时/个别测试。
3. mode
类型:字符串;取值:"ONLINE""OFFLINE"
含义:覆盖 TEST_MODEONLINE 走 API 全流程OFFLINE 读取 JSON 归档执行 Transform + Load。
4. db_dsn
类型字符串示例postgresql://user:pwd@host:5432/testdb。
含义:设置 TEST_DB_DSN使用真实 PostgreSQL 连接;不设置则使用伪 DB仅记录操作不落库
5. json_archive / json_temp
类型:字符串;示例:"tests/testdata_json""C:/tmp/json"
含义:离线模式所需的归档输入目录 / 临时输出目录。未设置时沿用 .env 或默认配置。
6. keyword
类型:字符串;示例:"ORDERS"
含义:等价 pytest -k可筛选测试名/节点,只运行包含该关键字的用例。
7. pytest_args
类型:字符串;示例:"-vv --maxfail=1"
含义:追加 pytest 命令行参数,用于控制日志、失败策略等。
8. env
类型:列表;示例:["STORE_ID=123","API_TOKEN=xxx"]。
含义:额外的环境变量,在调用 run_tests 前注入到 os.environ。
9. preset_meta
类型:字符串;仅用于描述场景,不会传给 run_tests纯注释
使用方式:
- 直接 F5 或 `python scripts/test_presets.py`:读取 AUTO_RUN_PRESETS 的预置并顺序执行。
- `python scripts/test_presets.py --preset offline_realdb`:临时指定要运行的组合。
- `python scripts/test_presets.py --list`:查看参数说明及所有预置详情。
"""
from __future__ import annotations
import argparse
import os
import subprocess
import sys
from typing import List
RUN_TESTS_SCRIPT = os.path.join(os.path.dirname(__file__), "run_tests.py")
# 默认自动运行的预置(可自定义顺序)
AUTO_RUN_PRESETS = ["offline_realdb"]
PRESETS = {
"online_orders": {
"suite": ["online"],
"mode": "ONLINE",
"keyword": "ORDERS",
"pytest_args": "-vv",
"preset_meta": "在线模式,仅跑订单任务并输出详细日志",
},
"offline_realdb": {
"suite": ["offline"],
"mode": "OFFLINE",
"db_dsn": "postgresql://local-Python:Neo-local-1991125@100.64.0.4:5432/LLZQ-test",
"json_archive": "tests/testdata_json",
"keyword": "ORDERS",
"preset_meta": "离线模式 + 真实测试库,用预置 JSON 回放并写入测试库",
},
}
def print_parameter_help() -> None:
print("=== 参数键说明 ===")
print("suite : 预置套件列表,如 ['online','offline']")
print("tests : 自定义 pytest 路径列表")
print("mode : TEST_MODEONLINE/ OFFLINE")
print("db_dsn : TEST_DB_DSN连接真实 PostgreSQL")
print("json_archive : TEST_JSON_ARCHIVE_DIR离线模式输入目录")
print("json_temp : TEST_JSON_TEMP_DIR离线模式临时目录")
print("keyword : pytest -k 过滤关键字")
print("pytest_args : 额外 pytest 参数(字符串)")
print("env : 附加环境变量,例如 ['KEY=VALUE']")
print("preset_meta : 仅用于注释说明")
print()
def print_presets() -> None:
if not PRESETS:
print("当前未定义任何预置,请在 PRESETS 中添加。")
return
for idx, (name, payload) in enumerate(PRESETS.items(), start=1):
comment = payload.get("preset_meta", "")
print(f"{idx}. {name}")
if comment:
print(f" 说明: {comment}")
for key, value in payload.items():
if key == "preset_meta":
continue
print(f" {key}: {value}")
print()
def resolve_targets(requested: List[str] | None) -> List[str]:
if not PRESETS:
raise SystemExit("Pre-sets 为空,请先在 PRESETS 中定义测试组合。")
def valid(names: List[str]) -> List[str]:
return [name for name in names if name in PRESETS]
if requested:
candidates = valid(requested)
missing = [name for name in requested if name not in PRESETS]
if missing:
print(f"警告:忽略未定义的预置 {missing}")
if candidates:
return candidates
auto = valid(AUTO_RUN_PRESETS)
if auto:
return auto
# 兜底:全部预置
return list(PRESETS.keys())
def run_presets(preset_names: List[str], dry_run: bool) -> None:
for name in preset_names:
cmd = [sys.executable, RUN_TESTS_SCRIPT, "--preset", name]
printable = " ".join(cmd)
if dry_run:
print(f"[Dry-Run] {printable}")
else:
print(f"\n>>> 执行: {printable}")
subprocess.run(cmd, check=False)
def main() -> None:
parser = argparse.ArgumentParser(description="测试预置仓库(集中配置即可批量触发 run_tests")
parser.add_argument("--preset", choices=sorted(PRESETS.keys()), nargs="+", help="指定要运行的预置命令")
parser.add_argument("--list", action="store_true", help="仅列出参数说明与所有预置")
parser.add_argument("--dry-run", action="store_true", help="仅打印命令,不执行 pytest")
args = parser.parse_args()
if args.list:
print_parameter_help()
print_presets()
return
targets = resolve_targets(args.preset)
run_presets(targets, dry_run=args.dry_run)
if __name__ == "__main__":
main()