"""bre 其余模块 create 链路冒烟(TestClient)。 覆盖 full_tc 未写入的模块: group/plan/trait/trial/trial_study/treatment/trial_study_entry/ pedigree/pollination/seed_treatment/planting/seedling/tree_photo/selection_result/selection_rule。 逐一 create 断言 200,并按依赖逆序清理。 运行: cd d:\dpb\dpb\backend C:\ai\miniconda3\envs\dpb\python.exe -X utf8 scripts/test_bre_create_chain_tc.py """ import os os.environ["ENVIRONMENT"] = "dev" os.environ["PYTHONUTF8"] = "1" import sys sys.path.insert(0, r"d:\dpb\dpb\backend") import main from fastapi.testclient import TestClient create_app = main.create_app TOKEN = None def login(client): global TOKEN d = {"username": "super", "password": "123456", "grant_type": "password", "login_type": "PC端"} r = client.post("/api/v1/system/auth/login", data=d) b = r.json() if r.status_code == 200 and b.get("code") == 0: TOKEN = b["data"]["access_token"]; return key = client.get("/api/v1/system/auth/captcha/get").json()["data"]["key"] client.post("/api/v1/system/auth/captcha/slider/complete", json={"captcha_key": key}) d["captcha_key"] = key r = client.post("/api/v1/system/auth/login", data=d) assert r.status_code == 200 and r.json().get("code") == 0, f"LOGIN FAIL {r.text[:200]}" TOKEN = r.json()["data"]["access_token"] def auth(): return {"Authorization": f"Bearer {TOKEN}"} def main_(): with TestClient(create_app()) as client: login(client) RUN = __import__("datetime").datetime.now().strftime("%H%M%S") created: list[tuple[str, int]] = [] # (domain, id),清理按此逆序 def c(name, domain, payload): r = client.post(f"/api/v1/bre/{domain}/create", headers=auth(), json=payload) ok = r.status_code == 200 print(f"[{'OK ' if ok else 'FAIL'}] create {name} -> HTTP {r.status_code}") if not ok: print(" BODY:", str(r.text)[:400]); sys.exit(1) obj = r.json()["data"] created.append((domain, obj["id"])) return obj site = c("site", "site", {"site_name": f"链基地{RUN}"}) plot = c("plot", "plot", {"site_id": site["id"], "plot_code": f"链{RUN}"}) target = c("target", "target", {"target_name": f"链目标{RUN}"}) g1 = c("germplasm f", "germplasm", {"cultivar_name": f"链父{RUN}"}) g2 = c("germplasm m", "germplasm", {"cultivar_name": f"链母{RUN}"}) personnel = c("personnel", "personnel", {"name": f"链人员{RUN}"}) combo = c("cross_combination", "cross_combination", { "combination_code": f"CC-{RUN}", "bre_target_id": target["id"], "female_parent_id": g1["id"], "male_parent_id": g2["id"], "cross_method": "artificial", "cross_year": 2026}) tree = c("tree", "tree", { "combination_id": combo["id"], "plot_id": plot["id"], "tree_no": f"T{RUN}", "row_no": 1, "col_no": 1, "planted_date": "2026-03-15", "status": "alive", "bre_personnel_id": personnel["id"]}) # 独立模块 group = c("group", "group", {"group_name": f"链组{RUN}"}) plan = c("plan", "plan", {"plan_code": f"PL{RUN}", "plan_name": f"链计划{RUN}"}) trait = c("trait", "trait", {"trait_code": f"tr_{RUN}", "trait_name": f"链性状{RUN}"}) # 试验链路 trial = c("trial", "trial", {"trial_name": f"链试验{RUN}"}) study = c("trial_study", "trial_study", {"trial_id": trial["id"], "study_name": f"链研究点{RUN}"}) treatment = c("treatment", "treatment", {"trial_study_id": study["id"], "factor": "肥", "level": "高"}) entry = c("trial_study_entry", "trial_study_entry", { "trial_study_id": study["id"], "entry_number": 1, "germplasm_id": g1["id"]}) # 育种流程子模块 c("pedigree", "pedigree", {"combination_id": combo["id"], "child_code": f"C{RUN}"}) c("pollination", "pollination", {"combination_id": combo["id"], "pollination_date": "2026-04-01"}) c("seed_treatment", "seed_treatment", {"combination_id": combo["id"], "treatment_method": "stratify"}) c("planting", "planting", {"combination_id": combo["id"], "plot_id": plot["id"], "planting_date": "2026-03-10"}) c("seedling", "seedling", {"combination_id": combo["id"]}) c("tree_photo", "tree_photo", {"combination_id": combo["id"], "tree_id": tree["id"], "photo_type": "whole"}) c("selection_result", "selection_result", { "combination_id": combo["id"], "tree_id": tree["id"], "is_selected": "primary"}) c("selection_rule", "selection_rule", { "target_id": target["id"], "rule_name": f"链规则{RUN}", "conditions_json": "{}"}) print("\n=== 清理(依赖逆序) ===") ORDER = ["tree_photo", "selection_result", "seedling", "planting", "seed_treatment", "pollination", "pedigree", "trait_observation", "tree", "tree_evaluation", "cross_combination", "trial_study_entry", "treatment", "trial_study", "trial", "selection_rule", "plan", "group", "germplasm", "personnel", "target", "trait", "plot", "site"] for domain in ORDER: ids = [o[1] for o in created if o[0] == domain] if not ids: continue r = client.request("DELETE", f"/api/v1/bre/{domain}/delete", headers=auth(), json=ids) status = "OK " if r.status_code in (200, 409) else "FAIL" print(f"[{status}] delete {domain} x{len(ids)} -> HTTP {r.status_code}") if r.status_code not in (200, 409): print(" BODY:", str(r.text)[:300]) print("\nALL CREATE CHAIN PASS ✅") if __name__ == "__main__": main_()