ServicesÀ proposNotesContact Me contacter →
EN FR
Note

Pyramide de test dbt

La pyramide de test en couches pour les projets dbt — large couverture de tests de données à la base, tests unitaires ciblés au milieu, détection d'anomalies et diffs de données au sommet.

Planté
dbttestingdata quality

Dans dbt, les tests de données forment la large base de la pyramide de test, pas les tests unitaires. Les problèmes de qualité des données (doublons, valeurs nulles, données obsolètes, valeurs invalides) sont plus courants que les bugs logiques dans les transformations SQL, donc la pyramide s’élargit à la couche présentant le risque le plus élevé.

La pyramide

/\
/ \ Diffs de données
/ \ (dbt-audit-helper)
/______\ Développement uniquement, à utiliser avec parcimonie
/ \
/ Détection \ Elementary
/ d'anomalies \ Tables clés uniquement
/______________\
/ \
/ Tests unitaires \ 5-10% des modèles
/ \ Logique complexe uniquement
/______________________\
/ \
/ Tests de données \ Large couverture
/____________________________\ Chaque PK, FKs critiques

Chaque couche remplit un objectif différent, détecte une catégorie différente de problèmes et a un profil de coût différent. Les couches sont complémentaires, pas redondantes — supprimer l’une d’entre elles crée un angle mort.

Couche 1 : Tests de données (Large couverture)

Le fondement. Ce sont les tests que tout projet dbt devrait avoir, quelle que soit sa taille ou sa complexité. Ils sont peu coûteux à configurer (quelques lignes de YAML), peu coûteux à exécuter (scans par colonne) et détectent la classe la plus courante d’échecs en production.

Tests de données génériques sur chaque modèle :

  • Clés primaires : unique + not_null sur le grain de chaque table. Non négociable. Les clés primaires en double causent des explosions de jointures en aval qui sont douloureuses à diagnostiquer et coûteuses à corriger.
  • Clés étrangères : relationships sur les jointures critiques. Toutes les clés étrangères n’ont pas besoin d’un test, mais celles qui alimentent les tableaux de bord et les métriques devraient être validées.
  • Enums : accepted_values sur les colonnes de statut et de type. Une valeur en amont inattendue (par exemple, "cancelled" orthographié différemment) casse silencieusement la logique CASE WHEN en aval.

dbt-expectations pour une couverture ciblée :

  • Patterns regex pour les emails, URLs, codes produits — tout ce qui a un format connu
  • Plages numériques pour les valeurs qui ont des bornes connues (revenu > 0, taux de conversion entre 0 et 1)
  • Comparaisons de nombre de lignes pour les transformations critiques où la perte de lignes serait invisible autrement

Cette couche s’exécute à chaque dbt build en production. Elle voit les données réelles. Elle détecte les problèmes que le code correct ne peut pas prévenir : les systèmes sources envoyant des données incorrectes, les APIs fournisseurs renvoyant des doublons, les équipes en amont changeant les schémas sans préavis.

Couche 2 : Tests unitaires (5-10% des modèles)

La couche du milieu. Les tests unitaires sont des outils à fort effort et haute précision. Ils utilisent des entrées mockées pour vérifier que la logique de transformation produit la sortie attendue pour des scénarios spécifiques. Ce sont les seuls outils qui peuvent détecter les bugs logiques avant qu’ils n’atteignent l’entrepôt.

Tous les modèles n’ont pas besoin de tests unitaires. Le consensus de la communauté est qu’environ 5 à 10% des modèles les méritent — spécifiquement ceux avec une logique complexe où les bugs sont genuinement plausibles :

  • Calculs avec plusieurs branches — instructions CASE WHEN multi-conditions où l’ordre des branches importe
  • Fonctions fenêtre — classement, totaux cumulés, calculs lag/lead où les définitions de frame de fenêtre sont délicates
  • Règles métier personnalisées — segmentation client, scoring de leads, calculs de remise avec cas limites
  • Tout ce qui a causé des bugs auparavant — le pattern « test sur échec » où un bug en production reçoit un test de régression

Les tests unitaires s’exécutent uniquement en CI. Ils utilisent des données mockées et n’apportent aucune valeur en production. Excluez-les des builds de production avec dbt build --exclude-resource-type unit_test.

L’insight clé : les tests unitaires et les tests de données ne sont pas des approches concurrentes. Ils détectent des catégories entièrement différentes de problèmes. Vos tests unitaires peuvent tous réussir pendant que vos tests de données échouent (les données sources sont cassées mais votre code est correct) et vice versa (votre code a un bug logique mais les données semblent plausibles par hasard).

Couche 3 : Détection d’anomalies (Tables clés uniquement)

La couche supérieure. Elementary adopte une approche fondamentalement différente des couches inférieures : au lieu de tester par rapport à des règles que vous définissez, il apprend ce qui est normal et alerte sur les déviations. Cela détecte les « inconnues inconnues » — les anomalies pour lesquelles vous n’auriez pas pensé à écrire des tests explicites.

Appliquez la détection d’anomalies de façon sélective aux tables métier clés :

  • Surveillance du volume sur les tables de faits — alerte quand les comptages de lignes dévient des patterns historiques. Détecte les échecs silencieux en amont où un modèle incrémentiel traite zéro lignes et réussit.
  • Fraîcheur sur les modèles adjacents aux sources — surveille le délai entre les mises à jour de façon adaptative, sans avoir à deviner et maintenir des seuils fixes.
  • Anomalies de colonnes sur les données financières — suit les métriques de distribution (moyenne, nombre de valeurs nulles, cardinalité) et signale les décalages. Une chute soudaine de 50% dans la valeur moyenne des commandes est techniquement dans les bornes mais signale un vrai problème.

Elementary s’exécute à chaque exécution de pipeline mais à un coût de calcul plus élevé que les tests de données parce qu’il interroge les données historiques pour établir des baselines. Maintenez des périodes d’entraînement raisonnables (14 à 30 jours) pour équilibrer précision et coût.

Couche 4 : Diffs de données (Développement uniquement)

Le sommet. dbt-audit-helper fournit une comparaison ligne par ligne entre deux relations — conçu spécifiquement pour valider les migrations et le refactoring.

{{ audit_helper.compare_queries(
a_query=old_query,
b_query=new_query,
primary_key='customer_id'
) }}

Cette couche est réservée au développement et à la CI. Ne jamais exécuter des diffs de données dans les pipelines de production. Ils sont coûteux (scans complets de table sur les deux relations), temporaires (pertinents uniquement pendant la période de migration) et diagnostiques (ils vous indiquent ce qui est différent, pas si c’est incorrect).

Cas d’utilisation :

  • Projets de refactoring majeurs où vous devez prouver que la nouvelle version produit des résultats identiques
  • Migration de scheduled queries legacy vers dbt
  • Validation qu’une optimisation de performance n’a pas modifié les sorties

Distribution recommandée

La forme de pyramide encode un principe important : investissez davantage dans les couches à couverture plus large et coût plus faible, moins dans les couches à couverture plus étroite et coût plus élevé.

Un projet bien testé typique peut ressembler à :

CoucheCouvertureCoût par testMaintenance
Tests de donnéesChaque modèleFaibleFaible — principalement configuration YAML
Tests unitaires5-10% des modèlesMoyenMoyen — les fixtures doivent être mises à jour quand les modèles changent
ElementaryTables métier clésPlus élevéMoyen — réglage de la sensibilité et des périodes d’entraînement
Diffs de donnéesMigrations actives uniquementLe plus élevéAucune une fois la migration terminée

Une erreur courante est d’inverser cette pyramide — écrire des tests unitaires pour tout en ignorant les tests de données de base. Un projet avec unique + not_null sur chaque clé primaire et aucun test unitaire détecte plus d’incidents en production qu’un projet avec des tests unitaires complets et aucune vérification de clé primaire.

Comment cela se relie à la stratégie par couche

La pyramide décrit quels types de tests utiliser et dans quelle proportion. La stratégie couche par couche décrit où dans le DAG les placer. Ce sont des cadres complémentaires :

  • Les tests de données (couche 1 de la pyramide) vont partout, mais avec une intensité croissante vers les bords du DAG
  • Les tests unitaires (couche 2 de la pyramide) se concentrent presque entièrement sur la couche mart où réside la logique métier complexe
  • Elementary (couche 3 de la pyramide) cible les tables de faits et les modèles adjacents aux sources où le volume et la fraîcheur importent le plus
  • Les diffs de données (couche 4 de la pyramide) sont utilisés pendant le développement quelle que soit la couche du DAG

Ensemble, les deux cadres répondent à la fois à « quel type de test ? » et « où le placer ? ». Pour le cadre de décision combiné qui réunit les deux dimensions, commencez par les trois questions de diagnostic.