Split backend tests into unit and integration suites, add isolated fixtures and coverage enforcement, and update CI and test documentation. Cover current authentication, content, notification, payment, media, and admin flows; fix behaviors revealed by the new tests. Validate both suites and the per-module gate against local PostgreSQL.
63 lines
2.0 KiB
Python
63 lines
2.0 KiB
Python
"""Enforce branch-aware coverage for every eligible backend module."""
|
|
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
EXCLUDED_NAMES = {"__init__.py", "apps.py"}
|
|
EXCLUDED_CONFIG = {
|
|
"config/asgi.py",
|
|
"config/wsgi.py",
|
|
"config/services/location.py",
|
|
"config/services/notifications.py",
|
|
"config/services/zarinpal.py",
|
|
}
|
|
|
|
|
|
def eligible_modules():
|
|
for source in ("apps", "core", "config"):
|
|
for path in (ROOT / source).rglob("*.py"):
|
|
relative = path.relative_to(ROOT).as_posix()
|
|
if path.name in EXCLUDED_NAMES or relative in EXCLUDED_CONFIG:
|
|
continue
|
|
if any(part in {"tests", "migrations"} for part in path.parts):
|
|
continue
|
|
if relative.startswith("config/settings/"):
|
|
continue
|
|
yield relative
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("coverage_json", type=Path)
|
|
parser.add_argument("--minimum", type=float, default=80.0)
|
|
args = parser.parse_args()
|
|
report = json.loads(args.coverage_json.read_text(encoding="utf-8"))
|
|
files = {name.replace("\\", "/"): data for name, data in report["files"].items()}
|
|
failures = []
|
|
for module in sorted(eligible_modules()):
|
|
data = files.get(module)
|
|
if data is None:
|
|
failures.append(f"{module}: absent from coverage report")
|
|
continue
|
|
summary = data["summary"]
|
|
total = summary["num_statements"] + summary["num_branches"]
|
|
if total == 0:
|
|
continue
|
|
covered = total - summary["missing_lines"] - summary["missing_branches"]
|
|
percent = covered * 100 / total
|
|
print(f"{percent:6.2f}% {module}")
|
|
if percent < args.minimum:
|
|
failures.append(f"{module}: {percent:.2f}% < {args.minimum:.2f}%")
|
|
if failures:
|
|
print("Coverage gate failed:")
|
|
for failure in failures:
|
|
print(f" {failure}")
|
|
raise SystemExit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|