feat(ldd): property-based, mutation и браузерный E2E
This commit is contained in:
68
scripts/ldd-mutation.sh
Executable file
68
scripts/ldd-mutation.sh
Executable file
@@ -0,0 +1,68 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user