#!/usr/bin/env bash # LDD mutation evidence: PIT для критичных P0-компонентов. # JUnit 4 harness используется потому, что JUnit5-плагин PIT несовместим с JUnit Platform 6. set -euo pipefail cd "$(dirname "$0")/.." ./gradlew \ :services:academic-service:pitestCourseAccess \ :services:identity-service:pitestPromotionPlanner \ --console=plain mkdir -p build/evidence python3 - <<'PY' import json import os import xml.etree.ElementTree as ET checks = [] def parse(path): root = ET.parse(path).getroot() total = killed = no_coverage = 0 for mutation in root.findall("mutation"): total += 1 status = mutation.attrib.get("status") if status == "KILLED": killed += 1 elif status == "NO_COVERAGE": no_coverage += 1 covered = total - no_coverage strength = (killed / covered * 100) if covered else 0.0 return total, killed, no_coverage, strength def check(check_id, path, threshold): if not os.path.isfile(path): checks.append({"id": check_id, "status": "failed", "detail": "нет отчёта " + path}) return total, killed, no_coverage, strength = parse(path) status = "passed" if strength >= threshold else "failed" detail = ( f"mutations={total}, killed={killed}, no_coverage={no_coverage}, " f"test_strength={strength:.1f}% (threshold {threshold:.0f}%)" ) checks.append({"id": check_id, "status": status, "detail": detail}) print(("PASS " if status == "passed" else "FAIL ") + check_id + ": " + detail) check( "mutation.course_access", "services/academic-service/build/reports/pitest-course-access/mutations.xml", 70.0, ) check( "mutation.promotion_planner", "services/identity-service/build/reports/pitest-promotion-planner/mutations.xml", 60.0, ) with open("build/evidence/mutation.json", "w", encoding="utf-8") as fh: json.dump({"generatedAt": __import__("datetime").datetime.now(__import__("datetime").UTC).isoformat(), "checks": checks}, fh, ensure_ascii=False, indent=2) if any(c["status"] != "passed" for c in checks): raise SystemExit(1) PY