Skip to content

Latest commit

 

History

History
100 lines (87 loc) · 6.91 KB

File metadata and controls

100 lines (87 loc) · 6.91 KB

Quality strategy

Safety chain

╔══════════════════════════════════════════════════════════════════════╗
║  git commit                                                          ║
║  ─────────────────────────────────────────────────────────────────  ║
║  pre-commit (automatic, ~10s)                                        ║
║                                                                      ║
║  ✦ ruff check     lint — style errors, common bugs                  ║
║  ✦ ruff format    formatting — code consistency                      ║
║  ✦ mypy           typing — strict annotations, no hidden Any         ║
║  ✦ bandit         static security — injections, hardcoded secrets    ║
║  ✦ trailing-whitespace / end-of-file / check-yaml / check-toml       ║
╚══════════════════════════════════════════════════════════════════════╝
                              │
                              ▼
╔══════════════════════════════════════════════════════════════════════╗
║  git push                                                            ║
║  ─────────────────────────────────────────────────────────────────  ║
║  pre-push (automatic, ~5–15s)                                        ║
║                                                                      ║
║  ✦ pytest tests/examples tests/shared                               ║
║    → pure tests, no I/O, fast regardless of project size            ║
║    → infrastructure and E2E tests reserved for CI                   ║
╚══════════════════════════════════════════════════════════════════════╝
                              │
                              ▼
╔══════════════════════════════════════════════════════════════════════╗
║  Pull Request → CI GitHub Actions                                    ║
║  ─────────────────────────────────────────────────────────────────  ║
║  Job: quality                           Job: security                ║
║  ✦ ruff check                           ✦ bandit (src/)             ║
║  ✦ ruff format --check                  ✦ pip-audit                 ║
║  ✦ mypy src                             ✦ xenon (complexity ≤ C)    ║
║                                                                      ║
║  Job: tests                             Job: mutation (PR → main)   ║
║  ✦ pytest (full suite)                  ✦ mutmut (examples/ only)   ║
║  ✦ coverage ≥ 80% (blocking)            → restricted for performance ║
║  ✦ upload to Codecov                                                 ║
╚══════════════════════════════════════════════════════════════════════╝
                              │
                              ▼
╔══════════════════════════════════════════════════════════════════════╗
║  Merge                                                               ║
║  ─────────────────────────────────────────────────────────────────  ║
║  ✦ PR checklist (manual — see CONTRIBUTING.md)                      ║
║  ✦ E2E tests on main (dedicated CI job, non-blocking on PR)         ║
╚══════════════════════════════════════════════════════════════════════╝

Tools and responsibilities

Tool When Blocking Scope
ruff commit + CI yes src/ + tests/
mypy commit + CI yes src/
bandit commit + CI yes src/
pip-audit CI yes all dependencies
xenon CI yes src/ — avg ≤ A, module ≤ B, function ≤ C
pytest (examples + shared) push yes tests/examples + tests/shared
pytest (full suite) CI yes tests/
coverage ≥ 80% CI yes src/
mutmut CI (PR → main) no src/my_project/examples/ only
pytest-benchmark manual (make benchmark) no tests/examples/test_benchmarks.py
E2E tests CI (main) no tests/e2e/

Test philosophy

Coverage is a proxy, not a goal. A test has value only if it can fail for the right reason.

  • Assert behaviour, not implementation — test what the code does, not how it does it
  • No pass-through tests — a test that always passes regardless of the code is worse than no test
  • One clear intent per test — if a test breaks, it must be obvious why
  • Coverage ≥ 80% is a floor, not a target — chasing 100% produces noise; mutmut reveals gaps that coverage misses

Local commands

make check      # mirrors the CI "quality" job (lint + format + types + security + complexity)
make test       # mirrors the CI "tests" job (full suite + coverage)
make ci         # runs the full CI pipeline locally
make benchmark  # performance benchmarks (excluded from normal run)
make mutation   # mutation testing on the domain slice (slow)
make complexity # complexity check only (xenon — average ≤ A, module ≤ B, function ≤ C)

Complexity grades (xenon/radon)

Xenon bloque le build si les seuils suivants sont dépassés :

Seuil Grade max autorisé Signification
--max-average A (1–5) Complexité moyenne du projet
--max-modules B (6–10) Pire module du projet
--max-absolute C (11–15) Pire fonction individuelle

Les grades vont de A (simple) à F (> 25 chemins, impossible à tester). Une fonction qui dépasse C est un signal de refactoring.