Le testing est la lacune de capacité la plus significative entre Dataform et dbt. Dataform fournit trois types d’assertions intégrées. L’écosystème dbt propose des dizaines de types de tests à travers plusieurs packages, plus des tests unitaires natifs. La différence est structurelle, pas incrémentale.
Ce que Dataform fournit
Le système d’assertions de Dataform est configuré directement dans le bloc config SQLX :
config { type: "table", assertions: { uniqueKey: ["customer_id"], nonNull: ["customer_id", "email"], rowConditions: ['email LIKE "%@%.%"'] }}uniqueKey valide que la colonne spécifiée (ou la combinaison de colonnes) ne contient pas de doublons. C’est l’équivalent du test générique unique de dbt.
nonNull garantit que les colonnes listées ne contiennent pas de valeurs nulles. Équivalent du test not_null de dbt.
rowConditions évalue des expressions SQL arbitraires contre chaque ligne. Toute ligne où la condition est fausse est signalée. C’est le plus flexible des trois, approximativement comparable à expression_is_true de dbt-utils.
Voilà le vocabulaire de testing intégré complet. Trois types d’assertions couvrant les vérifications de qualité des données les plus basiques.
Ce que Dataform n’a pas
Comparons avec ce que l’écosystème de testing dbt fournit :
Intégrité référentielle
Le test relationships de dbt valide que les valeurs de clés étrangères existent dans leur table parente. Dataform n’a pas d’équivalent intégré. Pour vérifier l’intégrité référentielle, il faut écrire un fichier d’assertion personnalisée — une requête SQL séparée qui retourne les lignes violant la relation. Pour un projet avec des dizaines de relations de clés étrangères, cela signifie des dizaines de fichiers d’assertions maintenus manuellement.
Validation statistique et par pattern
Le package dbt_expectations fournit plus de 50 tests portés depuis la bibliothèque Python Great Expectations :
expect_column_values_to_be_between— validation de plage détectant les valeurs impossibles comme un revenu négatif ou un taux de conversion supérieur à 1,0expect_column_values_to_match_regex— validation par pattern pour les emails, SKU, numéros de téléphoneexpect_column_mean_to_be_between— détection de dérive de distribution où les valeurs individuelles passent mais les agrégats signalent des problèmesexpect_row_values_to_have_recent_data— vérifications de fraîcheur sur n’importe quel modèle
Aucun de ces tests n’a d’équivalent Dataform. Chacun d’eux doit être écrit de zéro sous forme d’assertion personnalisée.
Détection d’anomalies
Elementary fournit une détection d’anomalies adaptative basée sur des patterns historiques plutôt que des seuils statiques :
volume_anomalies— déviation du nombre de lignes par rapport aux patterns historiquesfreshness_anomalies— surveillance adaptative de la fréquence de mise à jourcolumn_anomalies— suivi statistique des métriques au niveau des colonnesschema_changes— ajouts, suppressions ou changements de type de colonnes inattendus
Cette catégorie entière de testing des “inconnues inconnues” n’existe pas dans l’univers Dataform.
Tests unitaires
dbt 1.8 a introduit des tests unitaires natifs qui valident la logique de transformation avec des entrées mockées avant que les données ne touchent l’entrepôt :
unit_tests: - name: test_discount_calculation model: mrt__finance__orders given: - input: ref('base__shopify__orders') rows: - {order_id: 1, subtotal: 100, discount_code: "SAVE20"} expect: rows: - {order_id: 1, discount_amount: 20, final_total: 80}Les tests unitaires répondent à la question “mon SQL est-il correct ?” plutôt que “mes données sont-elles saines ?”. Dataform n’a aucun mécanisme équivalent. Il est impossible de tester la logique de transformation de manière isolée sans l’exécuter contre des données réelles.
Les assertions personnalisées dans Dataform
La porte de sortie de Dataform est le fichier d’assertion personnalisée. On crée un fichier .sqlx avec type: "assertion" qui retourne les lignes violant une condition :
config { type: "assertion", schema: "assertions"}
-- Échoue si un client a une valeur vie négativeSELECT customer_id, lifetime_valueFROM ${ref("mrt_customers")}WHERE lifetime_value < 0Si la requête retourne des lignes, l’assertion échoue. C’est l’équivalent des tests singuliers de dbt. Cela fonctionne, mais chaque assertion est un fichier séparé avec du SQL écrit à la main. Il n’y a pas de paramétrage, pas de pattern de réutilisation, pas de bibliothèque de tests sur laquelle s’appuyer.
Le package dataform-assertions de Devoteam est l’une des rares options tierces disponibles, fournissant quelques patterns d’assertions réutilisables. Mais c’est un seul package communautaire face à l’écosystème de centaines de packages de dbt.
L’impact pratique
Pour les projets avec des besoins de testing basiques — unicité des clés primaires, contrôles de nullité, quelques règles métier — les assertions de Dataform sont adéquates. Beaucoup de petits projets n’ont genuinement pas besoin de tests de distribution statistique ou de détection d’anomalies.
L’écart devient douloureux à mesure que la complexité augmente. Un projet avec plus de 100 modèles, des dizaines de relations de clés étrangères, et des exigences de qualité des données critiques pour l’activité passera un temps d’ingénierie significatif à construire des assertions personnalisées que les équipes dbt obtiennent d’emblée. Ce temps d’ingénierie est un coût réel qui compense le prix zéro de la licence Dataform.
L’écart de testing est auto-renforçant. Les équipes manquant d’outils de testing faciles ont tendance à écrire moins de tests. La friction d’écrire des assertions personnalisées pour chaque nouveau type de test signifie que de nombreux tests valides ne sont jamais écrits. Dans dbt, ajouter un test relationships c’est une ligne de YAML. Dans Dataform, cela requiert un nouveau fichier avec une requête personnalisée. La différence de friction détermine la différence de couverture.