#!/usr/bin/env python3 """选择 ACK 回归目录中的 active 用例。 默认返回 smoke 套件。本脚本只输出数据,不执行 steps 或 automationRef。 用法: python3 select_regression.py .pouch/ack/regression.yaml python3 select_regression.py .pouch/ack/regression.yaml --suite full python3 select_regression.py .pouch/ack/regression.yaml --case-id REG-login-001 """ from __future__ import annotations import argparse import json import sys from pathlib import Path from typing import Any from validate_regression import ID_RE, load_yaml, validate_builtin DEFAULT_LIMIT = 50 MAX_LIMIT = 200 def select_cases( data: dict[str, Any], *, suite: str, case_ids: list[str], limit: int, ) -> list[dict[str, Any]]: cases = data.get("cases") if not isinstance(cases, list): raise ValueError("cases 必须是列表") wanted = set(case_ids) selected: list[dict[str, Any]] = [] for case in cases: if not isinstance(case, dict): continue if case.get("status") != "active": continue case_id = case.get("id") if wanted: if case_id not in wanted: continue elif suite == "smoke" and case.get("suite") != "smoke": continue selected.append(case) missing = wanted - { case.get("id") for case in selected if isinstance(case.get("id"), str) } if missing: raise ValueError("找不到 active 用例: " + ", ".join(sorted(missing))) if len(selected) > limit: raise ValueError( f"命中 {len(selected)} 条,超过 --limit {limit};" "请用 --suite / --case-id 缩小范围" ) return selected def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser(description="选择 ACK 回归用例") parser.add_argument( "regression", nargs="?", default=".pouch/ack/regression.yaml" ) parser.add_argument( "--suite", choices=("smoke", "full"), default="smoke", help="smoke 只返回 suite=smoke;full 返回全部 active 用例", ) parser.add_argument("--case-id", action="append", default=[], dest="case_ids") parser.add_argument("--limit", type=int, default=DEFAULT_LIMIT) parser.add_argument( "--format", choices=("json", "ids"), default="json", dest="output_format" ) args = parser.parse_args(argv) regression_path = Path(args.regression) if not regression_path.is_file(): sys.stderr.write(f"找不到回归目录: {regression_path}\n") return 2 if not 1 <= args.limit <= MAX_LIMIT: sys.stderr.write(f"--limit 必须在 1..{MAX_LIMIT} 之间\n") return 2 for case_id in args.case_ids: if ID_RE.fullmatch(case_id) is None: sys.stderr.write(f"--case-id 必须使用 REG- 格式: {case_id}\n") return 2 data = load_yaml(regression_path, "回归目录") errors = validate_builtin(data) if errors: sys.stderr.write(f"回归目录无效,拒绝选择,共 {len(errors)} 项:\n") for error in errors: sys.stderr.write(f" - {error}\n") return 1 try: selected = select_cases( data, suite=args.suite, case_ids=args.case_ids, limit=args.limit, ) except ValueError as exc: sys.stderr.write(f"回归选择失败: {exc}\n") return 1 ids = [case.get("id") for case in selected] if args.output_format == "ids": if ids: sys.stdout.write("\n".join(str(item) for item in ids) + "\n") return 0 payload = { "count": len(selected), "limit": args.limit, "suite": args.suite, "ids": ids, "cases": selected, } sys.stdout.write(json.dumps(payload, ensure_ascii=False, indent=2) + "\n") return 0 if __name__ == "__main__": raise SystemExit(main())