Project

General

Profile

Feature #47 » qa-47-preuve-technique.txt

Redmine Admin, 06/11/2026 07:51 PM

 
===================================================================
QA #47 — Infrastructure Redmine : recherche par clé (champ custom),
création + anti-doublons/régression
Epic parent : #24 | Branche : feat/47-redmine-security-adapter
PR #27 -> dev | Backend uniquement (api/)
SHA testé : bf0d87d (origin/feat/47-redmine-security-adapter)
Date : 2026-06-11 | Agent : QA manuel (#25)
NOTE : aucun secret/clé API n'est inclus dans cette preuve.
===================================================================

ENVIRONNEMENT
python : api/.venv (FastAPI épinglé)
cmd : PYTHONPATH=src .venv/bin/python -m pytest -q tests/test_redmine_scan_adapter.py

-------------------------------------------------------------------
SMOKE TEST 1/3 — Tests de contrat respx (9 tests, hors réseau)
-------------------------------------------------------------------
......... [100%]
9 passed in 0.46s

-------------------------------------------------------------------
SMOKE TEST 1/3 — détail (verbose, noms de scénarios)
-------------------------------------------------------------------
tests/test_redmine_scan_adapter.py::test_adapter_is_a_scan_ticket_port PASSED [ 11%]
tests/test_redmine_scan_adapter.py::test_find_by_key_open_ticket_via_custom_field PASSED [ 22%]
tests/test_redmine_scan_adapter.py::test_find_by_key_no_match_returns_none PASSED [ 33%]
tests/test_redmine_scan_adapter.py::test_find_by_key_only_closed_ticket_is_regression PASSED [ 44%]
tests/test_redmine_scan_adapter.py::test_find_by_key_fallback_matches_on_description PASSED [ 55%]
tests/test_redmine_scan_adapter.py::test_create_ticket_files_security_ticket PASSED [ 66%]
tests/test_redmine_scan_adapter.py::test_create_ticket_without_field_embeds_key_in_body PASSED [ 77%]
tests/test_redmine_scan_adapter.py::test_reopen_ticket_resets_status_and_notes PASSED [ 88%]
tests/test_redmine_scan_adapter.py::test_note_still_open_adds_note_only PASSED [100%]

-------------------------------------------------------------------
SMOKE TEST 2/3 — Câblage import / use-case
-------------------------------------------------------------------
OK : RedmineScanTicketAdapter implémente ScanTicketPort (port défini en #46)
OK : build_redmine_scan_ticket_adapter + SECURITY_TAG importables
OK : RedmineField.SECURITY_KEY = 12
OK : SECURITY_TAG = [Sécurité]

-------------------------------------------------------------------
SMOKE TEST 3/3 — Qualité statique (module concerné)
-------------------------------------------------------------------
$ ruff check scan_adapter.py + test_redmine_scan_adapter.py
All checks passed!
$ mypy scan_adapter.py
Success: no issues found in 1 source file

===================================================================
MAPPING CRITÈRES D'ACCEPTATION -> RÉSULTAT
===================================================================
AC1 Recherche par clé via champ custom 'security_key' (id 12),
avec repli titre/description documenté ............... OK
- test_find_by_key_open_ticket_via_custom_field
- test_find_by_key_fallback_matches_on_description
- docstring scan_adapter.py : repli documenté (lignes 21-26)
AC2 Anti-doublon : aucun ticket si un ticket OUVERT porte
déjà la clé (resolved=False) ......................... OK
- test_find_by_key_open_ticket_via_custom_field
- requête pass 1 scoping status_id=open vérifié
AC3 Régression : nouveau ticket si seuls des tickets
FERMÉS portent la clé (resolved=True) ................ OK
- test_find_by_key_only_closed_ticket_is_regression
AC4 Création conforme : tag [Sécurité], statut Submitted,
clé persistée dans security_key ...................... OK
- test_create_ticket_files_security_ticket
- test_create_ticket_without_field_embeds_key_in_body
AC5 Tests respx verts ; chemin RUN_REDMINE_LIVE présent ;
ruff + mypy passent .................................. OK
- 9/9 respx verts ; ruff+mypy clean ; gate dev :
423 passed / 2 skipped (live gated) x2

NOTE AC1 (provisioning) : le champ custom security_key (id 12)
n'est pas encore provisionné sur le Redmine live ; l'adaptateur
retombe alors sur le repli titre/description (clé embarquée dans
le corps à la création). Comportement vérifié par
test_find_by_key_fallback_matches_on_description et
test_create_ticket_without_field_embeds_key_in_body.

VERDICT : PASS — tous les critères OK.
===================================================================
    (1-1/1)