bash
import os
import json
from pathlib import Path
ALLURE_RESULTS_DIR = "report"# allure结果目录
PYTEST_BASE_CMD = "pytest -v --alluredir=report "
defallure_fullname_to_nodeid(fullname: str) -> str:
"""
将 allure fullName 转换为 pytest nodeid
e.g.
-> test_case/xxx.py::TestClass::test_func
"""
if"#"notin fullname:
return fullname
module_part, func_name = fullname.split("#", 1)
parts = module_part.split(".")
# 最后一个是类名
class_name = parts[-1]
file_path = "/".join(parts[:-1]) + ".py"
returnf"{file_path}::{class_name}::{func_name}"
defget_latest_failed_or_broken_cases(allure_results_dir):
case_latest = {} # {fullName: (timestamp, status, nodeid)}
for file in Path(allure_results_dir).glob("*.json"):
try:
withopen(file, "r", encoding="utf-8") as f:
data = json.load(f)
except Exception:
continue
full_name = data.get("fullName")
status = data.get("status")
start = data.get("start", 0)
ifnot full_name:
continue
nodeid = allure_fullname_to_nodeid(full_name)
# 如果这个 case 没见过,或者发现更新的执行记录 → 覆盖
if (full_name notin case_latest) or (start > case_latest[full_name][0]):
case_latest[full_name] = (start, status, nodeid)
# 只留下最新是 failed/broken 的
return [v[2] for v in case_latest.values() if v[1] in {"failed", "broken"}]
defbuild_pytest_cmd(cases):
ifnot cases:
return"echo 'No failed/broken cases found'"
return PYTEST_BASE_CMD + " ".join(cases)
if __name__ == "__main__":
cases = get_latest_failed_or_broken_cases(ALLURE_RESULTS_DIR)
for i insorted(cases):
print(i)
cmd = build_pytest_cmd(cases)
print("重跑命令:")
print(cmd)
print(len(cases))
输出:
nodeid#Python