Skip to content

Stratégie de tests — CVN-N014-ED-S01 (object-storage XCom backend flip)

Réfs : plan dossier · architecture · runbook. Taxonomie : ADR-83 (tiers fast/medium/nightly/operator-driven + marqueur story). Principe directeur : les livrables S01 sont des outils read-only in-pod + un standard. La logique pure (classification, verdicts, invariants read-only) est testable unitairement et déterministe, hors cluster. Le comportement in-pod réel (round-trip, config effective) relève de la validation système (dogfood contre le scheduler réel), déjà exécutée.


1. Objectifs & périmètre

Tester : (a) la correction du classifieur d'audit (json_literal / numpy_suspect / unknown) ; (b) la sémantique de verdict du round-trip (régression contrôle-flow bloque ; numpy EXPECTED-FAIL ne bloque pas) ; (c) les invariants read-only des sondes embarquées (aucune écriture XCom/DB ; le write S3 du pre-flight est gated par --functional-s3) ; (d) le footgun config (le pre-flight lit la section pointée common.io).

Ne PAS tester (relève d'autre chose) : la valeur réelle du round-trip in-pod et de la config effective (= validation système, dogfood cluster, déjà fait) ; le flip prod lui-même (= staged, gated rehearsal) ; la stratégie numpy (= S02).

2. Pyramide de tests + tiers ADR-83

Niveau Marqueur Tier Ce qui est testé Fichier
Classifieur audit (pur) unit fast (PR-blocking) json_literal / numpy_suspect / unknown ; @task vs fonction nue ; push value kwarg/positional ; pull/output = consommation ; parse-error surfacé ; path absent tests/unit/test_xcom_serialization_audit.py
Verdict round-trip (pur) unit fast all-green → 0 ; régression contrôle-flow → 1 ; numpy EXPECTED-FAIL → 0 ; jeux de cas disjoints + couvrant le corpus ; invariant read-only de la sonde tests/unit/test_xcom_roundtrip_probe.py
Pre-flight (pur) unit fast lit la section pointée common.io ; vérifie provider + connexion ; write S3 gated par --functional-s3 ; functional off par défaut ; check FAIL → exit non-zéro tests/unit/test_xcom_flip_preflight.py

Tous portent @pytest.mark.story("CVN-N014-ED-S01") (ADR-87, filtre pytest --story). 19 tests, tier fast, verts.

3. Cas de tests — couche AUDIT (le cœur du classifieur)

# Entrée Classification attendue Pourquoi
A1 @taskreturn {'auc':0.5,'ok':True} json_literal dict de constantes = flip-safe
A2 @taskreturn {'P': np.vstack(rows)} numpy_suspect np/vstack ⇒ non-JSON
A3 @taskreturn df.to_numpy() numpy_suspect pandas → numpy
A4 ti.xcom_push(key=..., value={'a':1}) json_literal value kwarg constant
A5 ti.xcom_push('k', some_ndarray) unknown Name non résoluble → à probe-r, pas un faux json_literal
A6 xcom_pull(...) / .output n/a (consommation) sites de lecture, pas de producteur
A7 fonction nue (sans @task) renvoyant numpy aucun finding ce n'est pas un XCom
A8 source non-parsable parse_error surfacé (pas de crash) ADR-25
A9 path inexistant FileNotFoundError fail-fast

4. Cas de tests — couche VERDICT (round-trip) & READ-ONLY

  • V1 all-green → exit 0 ; V2 régression contrôle-flow → exit 1 ; V3 numpy EXPECTED-FAIL (tous) + contrôle-flow OK → exit 0 ; V4 jeux CONTROL_FLOW_CASES / EXPECTED_FAIL_CASES disjoints et couvrant le corpus de la sonde.
  • R1 (read-only) : la sonde round-trip ne contient ni xcom_push, ni session, ni execute(, ni SQL d'écriture, ni create_engine ; elle fait json.dumps(val, cls=XComEncoder).
  • P1 (pre-flight footgun) : la sonde lit conf.get("common.io", "xcom_objectstorage_{path,threshold}") + core.xcom_backend ; P2 le write S3 est sous if req.get("functional") ; P3 --functional-s3 absent ⇒ functional=False ; P4 un check FAIL ⇒ exit non-zéro.

5. Validation système (dogfood — déjà exécutée)

Hors test unitaire, contre le scheduler réel (airflow-scheduler-…-jsmhp) :

Outil Run réel Résultat
xcom_serialization_audit.py --path dags 129 sites 0 numpy_suspect, 116 unknown, 1 json_literal
xcom_roundtrip_probe.py corpus + forme s43 contrôle-flow GREEN (3/3), numpy EXPECTED-FAIL (3/3), exit 0
xcom_flip_preflight.py (read-only) provider + config provider OK, backend=BaseXCom, threshold=-1 (prouvés in-pod)
airflow config get-value core enable_xcom_pickling False effectif (clé de voûte H1)

6. Hors-scope test (par conception)

  • Le flip prod et son round-trip d'offload réel : exigent un payload > seuil (post-S02) + un rehearsal kill-switch — validation système gated, pas test.
  • La serde numpy : c'est S02 (X′/X″/Y).
  • Recommandation comité (suivi) : automatiser le round-trip d'offload (gros JSON) en CI ; audit récurrent (trimestriel) sur le jeu de DAGs le plus large.