Avant de commencer
Dans la console Google Cloud , accédez à la page Dataform.
Sélectionnez ou créez un dépôt.
Sélectionnez ou créez un espace de travail de développement.
Rôles requis
Pour obtenir les autorisations nécessaires pour créer des assertions et des tests unitaires, demandez à votre administrateur de vous accorder les rôles IAM suivants :
- Éditeur Dataform (
roles/dataform.editor) sur l'espace de travail -
Pour synchroniser les métadonnées d'assertion avec Knowledge Catalog :
Éditeur de catalogue Dataplex (
roles/dataplex.catalogEditor) sur le projet ou le groupe d'entrées@bigquery
Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.
Vous pouvez également obtenir les autorisations requises avec des rôles personnalisés ou d'autres rôles prédéfinis.
Tester des données avec des assertions
Une assertion est une requête de test de qualité des données qui trouve les lignes qui ne respectent pas une ou plusieurs conditions spécifiées dans la requête. Si la requête renvoie un résultat, l'assertion échoue. Dataform exécute des assertions chaque fois qu'il met à jour votre workflow. Il vous alerte en cas d'échec.
Dataform crée automatiquement des vues dans BigQuery qui contiennent les résultats des requêtes d'assertion compilées. Comme configuré dans le fichier de paramètres de votre workflow, Dataform crée ces vues dans un schéma d'assertions où vous pouvez inspecter les résultats des assertions.
Par exemple, pour le schéma dataform_assertions par défaut, Dataform crée une vue dans BigQuery au format suivant : dataform_assertions.assertion_name.
Vous pouvez créer des assertions pour tous les types de tables Dataform : tables, tables incrémentielles, vues et vues matérialisées.
Vous pouvez créer des assertions de différentes manières :
Ajoutez des assertions intégrées au bloc de configuration d'un tableau.
Vous pouvez ajouter des assertions intégrées au bloc
configd'un tableau et spécifier leurs conditions.Ajoutez des assertions manuelles dans un fichier SQLX distinct.
Vous écrivez manuellement des assertions personnalisées dans un fichier SQLX distinct pour les cas d'utilisation avancés ou pour les ensembles de données qui ne sont pas créés par Dataform.
Créer des assertions intégrées
Vous pouvez ajouter des assertions Dataform intégrées au bloc config d'une table. Dataform exécute ces assertions après la création de la table. Une fois que Dataform a créé la table, vous pouvez vérifier si l'assertion a réussi dans l'onglet Journaux d'exécution du workflow de votre espace de travail.
Vous pouvez créer les assertions suivantes dans le bloc config d'une table :
nonNullCette condition affirme que les colonnes spécifiées ne sont pas nulles dans toutes les lignes du tableau. Cette condition est utilisée pour les colonnes qui ne peuvent jamais être nulles.
L'exemple de code suivant montre une assertion
nonNulldans le blocconfigd'un tableau :
config {
type: "table",
assertions: {
nonNull: ["user_id", "customer_id", "email"]
}
}
SELECT ...
rowConditionsCette condition affirme que toutes les lignes du tableau suivent la logique personnalisée que vous définissez. Chaque condition de ligne est une expression SQL personnalisée, et chaque ligne de tableau est évaluée par rapport à chaque condition de ligne. L'assertion échoue si une ligne du tableau renvoie
false.L'exemple de code suivant montre une assertion
rowConditionspersonnalisée dans le blocconfigd'une table incrémentielle :
config {
type: "incremental",
assertions: {
rowConditions: [
'signup_date is null or signup_date > "2022-08-01"',
'email like "%@%.%"'
]
}
}
SELECT ...
uniqueKeyCette condition affirme qu'aucune ligne du tableau n'a la même valeur dans une colonne spécifiée.
L'exemple de code suivant montre une assertion
uniqueKeydans le blocconfigd'une vue :
config {
type: "view",
assertions: {
uniqueKey: ["user_id"]
}
}
SELECT ...
uniqueKeysCette condition affirme qu'aucune ligne du tableau ne présente la même valeur dans les colonnes spécifiées. L'assertion échoue si la table comporte plusieurs lignes avec les mêmes valeurs pour toutes les colonnes spécifiées.
L'exemple de code suivant montre une assertion
uniqueKeysdans le blocconfigd'un tableau :
config {
type: "table",
assertions: {
uniqueKeys: [["user_id"], ["signup_date", "customer_id"]]
}
}
SELECT ...
Ajouter des assertions au bloc config
Pour ajouter des assertions au bloc de configuration d'un tableau, procédez comme suit :
- Dans votre espace de travail de développement, dans le volet Fichiers, sélectionnez un fichier SQLX de définition de table.
- Dans le bloc
configdu fichier de table, saisissezassertions: {}. - Dans
assertions: {}, ajoutez vos assertions. - Facultatif : Cliquez sur Format.
L'exemple de code suivant montre les conditions ajoutées dans le bloc config :
config {
type: "table",
assertions: {
uniqueKey: ["user_id"],
nonNull: ["user_id", "customer_id"],
rowConditions: [
'signup_date is null or signup_date > "2019-01-01"',
'email like "%@%.%"'
]
}
}
SELECT ...
Créer des assertions manuelles avec SQLX
Les assertions manuelles sont des requêtes SQL que vous écrivez dans un fichier SQLX dédié. Une requête SQL d'assertion manuelle doit renvoyer zéro ligne. Si la requête renvoie des lignes lorsqu'elle est exécutée, l'assertion échoue.
Pour ajouter des assertions manuelles dans un nouveau fichier SQLX, procédez comme suit :
- Dans le volet Fichiers, à côté de
definitions/, cliquez sur le menu
Plus. - Cliquez sur Créer un fichier.
Dans le champ Ajouter un chemin d'accès au fichier, saisissez le nom du fichier suivi de
.sqlx. Par exemple,definitions/custom_assertion.sqlx.Les noms de fichiers ne peuvent contenir que des chiffres, des lettres, des traits d'union et des traits de soulignement.
Cliquez sur Créer un fichier.
Dans le volet Fichiers, cliquez sur le nouveau fichier.
Dans le fichier, saisissez :
config { type: "assertion" }Sous le bloc
config, rédigez votre requête SQL ou plusieurs requêtes.Facultatif : Cliquez sur Format.
L'exemple de code suivant montre une assertion manuelle dans un fichier SQLX qui affirme que les champs A, B et c ne sont jamais NULL dans sometable :
config { type: "assertion" }
SELECT
*
FROM
${ref("sometable")}
WHERE
a IS NULL
OR b IS NULL
OR c IS NULL
Tester la qualité des données avec des tests unitaires
Un test unitaire est un test de qualité des données, défini dans un fichier .sqlx dédié, qui simule toutes les dépendances de l'action de workflow testée et fournit les résultats attendus.
Vous pouvez utiliser des tests unitaires pour tester les actions Dataform par rapport à des entrées fictives contrôlées afin de vérifier si le code d'action gère correctement les cas extrêmes, les valeurs nulles, les agrégations, les expressions régulières et la logique conditionnelle.
Les mocks pour les dépendances d'actions, telles que les tables, les vues ou les déclarations brutes prédécesseurs référencées dans la fonction ${ref()}, sont définis dans les blocs input. Chaque bloc input fait référence à une dépendance par son nom et contient une requête SQL qui définit les lignes fictives. Cette requête est généralement une série d'instructions SELECT combinées à UNION ALL.
Les résultats attendus sont des requêtes SQL qui représentent les résultats de l'exécution des entrées spécifiées sur l'instruction SQL de l'action de workflow.
Dataform exécute les tests unitaires ligne par ligne et compare le résultat réel de l'exécution de la logique SQL d'une action de workflow sur des données fictives avec un ensemble de résultats attendus.
Les tests unitaires peuvent avoir les états suivants :
SUCCESS: le test a réussi. Les résultats réels correspondent aux résultats attendus.FAILURE: le test a échoué. Les résultats réels ne correspondent pas aux résultats attendus.
Limites
Les tests unitaires Dataform sont disponibles avec les limites suivantes :
- Les tests unitaires sont disponibles avec Dataform Core version
3.0.56et ultérieure. - La taille maximale des données d'entrée dans un test unitaire est de 100 lignes par entrée.
Créer des tests unitaires
Stockez les fichiers .sqlx pour les tests unitaires dans le répertoire definitions/.
Pour créer un fichier de test unitaire .sqlx dans le répertoire definitions/, procédez comme suit :
Dans la console Google Cloud , accédez à la page Dataform.
Sélectionnez un dépôt.
Sélectionnez un espace de travail de développement.
Dans le volet Fichiers, à côté de
definitions/, cliquez sur le menu Plus.Cliquez sur Créer un fichier.
Dans le volet Créer un fichier, procédez comme suit :
Dans le champ Ajouter un chemin d'accès au fichier, après
definitions/, saisissez le nom du fichier suivi de_test.sqlx. Par exemple,definitions/customer_spend_test.sqlx.Les noms de fichiers ne peuvent contenir que des chiffres, des lettres, des traits d'union et des traits de soulignement.
Cliquez sur Créer un fichier.
Dans le fichier de test, ajoutez le bloc
configsuivant :config { type: "test", dataset: "ACTION_NAME" }Remplacez ACTION_NAME par le nom de l'action que ce test valide.
Pour simuler l'action testée, ajoutez un bloc
inputpour chaque dépendance d'action et écrivez une requête SQL testant cette dépendance au format suivant :input "DEPENDENCY_NAME" { SELECT ... SELECT ... }Remplacez DEPENDENCY_NAME par le nom de la dépendance d'action testée que cette entrée simule.
Sous les blocs
input, écrivez des requêtes SQL standard représentant les lignes de sortie attendues au format suivant :-- Expected Output SELECT ... SELECT ...
Les requêtes de sortie attendues ne doivent renvoyer que les lignes et les colonnes que l'action testée est censée produire à partir des entrées fictives.
L'exemple de code suivant montre l'action de workflow customer_spend.sqlx :
config {
type: "table",
name: "customer_spend"
}
SELECT
c.customer_id,
c.name,
SUM(o.amount) AS total_completed_amount
FROM
${ref("source_customers")} c
JOIN
${ref("source_orders")} o
ON c.customer_id = o.customer_id
WHERE
o.status = 'COMPLETED'
GROUP BY
1, 2
L'exemple de code suivant montre le test unitaire customer_spend_test.sqlx qui simule les dépendances de l'action customer_spend.sqlx et définit les résultats attendus pour les simulations :
config {
type: "test",
dataset: "customer_spend"
}
input "source_customers" {
SELECT 101 AS customer_id, 'Alice' AS name UNION ALL
SELECT 102 AS customer_id, 'Bob' AS name UNION ALL
SELECT 103 AS customer_id, 'Charlie' AS name
}
input "source_orders" {
-- Alice has one completed and one pending order
SELECT 1 AS order_id, 101 AS customer_id, 'COMPLETED' AS status, 100.0 AS amount UNION ALL
SELECT 2 AS order_id, 101 AS customer_id, 'PENDING' AS status, 50.0 AS amount UNION ALL
-- Bob has one completed order
SELECT 3 AS order_id, 102 AS customer_id, 'COMPLETED' AS status, 250.0 AS amount UNION ALL
-- Charlie has no orders
SELECT 4 AS order_id, 999 AS customer_id, 'COMPLETED' AS status, 10.0 AS amount
}
-- Expected Output
SELECT 101 AS customer_id, 'Alice' AS name, 100.0 AS total_completed_amount UNION ALL
SELECT 102 AS customer_id, 'Bob' AS name, 250.0 AS total_completed_amount
Exécuter des tests unitaires
Pour exécuter des tests unitaires, procédez comme suit :
Console
Dans la console Google Cloud , accédez à la page Dataform.
Sélectionnez un dépôt.
Sélectionnez un espace de travail de développement.
Cliquez sur Démarrer l'exécution > Exécuter les actions.
Dans le panneau Exécuter, dans la section Mode d'exécution, sélectionnez Tests unitaires.
Sélectionnez l'une des options suivantes :
- Sélectionner des tests unitaires : exécute les tests unitaires que vous sélectionnez manuellement.
- Sélectionner les tests unitaires tagués : exécute les tests unitaires avec un tag sélectionné.
- Tous les tests unitaires : exécute tous les tests unitaires de l'espace de travail.
(Facultatif) Dans la section Options d'exécution, cochez la case Exécuter en tant que job interactif avec une priorité élevée pour exécuter immédiatement les tests unitaires, en privilégiant la vitesse d'exécution.
Si vous ne cochez pas la case Exécuter en tant que job interactif avec une priorité élevée, Dataform exécute les tests unitaires à l'aide de ressources par lot par défaut, en privilégiant les économies sur les coûts de calcul.
Cliquez sur Démarrer l'exécution.
API
Pour exécuter des tests unitaires de manière programmatique, créez un appel de workflow à l'aide de la méthode WorkflowInvocations.create et définissez les paramètres d'exécution des tests unitaires suivants dans l'objet invocationConfig :
"executionMode": "UNIT_TESTS_ONLY"- Ce paramètre, défini sur
"UNIT_TESTS_ONLY", déclenche l'exécution des tests unitaires définis dans le dépôt. - Facultatif :
"queryPriority": "INTERACTIVE" - Lorsque ce paramètre est défini sur
"INTERACTIVE", Dataform exécute les requêtes immédiatement. Si elle n'est pas définie, Dataform exécute les tests unitaires avec la priorité des requêtes par lot par défaut. - Facultatif :
"includedTargets": [] - Ce paramètre vous permet de spécifier des tests unitaires afin que Dataform n'exécute que ces tests.
- Facultatif :
"includedTags": [] - Ce paramètre vous permet de spécifier des tags afin que Dataform n'exécute que les tests unitaires associés à ces tags.
L'exemple de code suivant montre le corps d'un appel de workflow qui exécute tous les tests unitaires définis dans le dépôt my-repo avec la priorité de requête par lot par défaut :
{
"compilationResult": "projects/my-project/locations/us/repositories/my-repo/compilationResults/my-compilation-id",
"invocationConfig": {
"executionMode": "UNIT_TESTS_ONLY"
}
}
L'exemple de code suivant montre le corps d'un appel de workflow qui n'exécute que le test unitaire my-test avec la priorité de requête interactive :
{
"compilationResult": "projects/my-project/locations/us/repositories/my-repo/compilationResults/my-compilation-id",
"invocationConfig": {
"executionMode": "UNIT_TESTS_ONLY",
"queryPriority": "INTERACTIVE",
"includedTargets": [
{
"database": "my-project",
"schema": "my-dataset",
"name": "my-test"
}
]
}
}
L'exemple de code suivant montre le corps d'un appel de workflow qui exécute des tests unitaires dans le dépôt my-repo tagués avec test-tag-1 ou test-tag-2 :
{
"compilationResult": "projects/my-project/locations/us/repositories/my-repo/compilationResults/my-compilation-id",
"invocationConfig": {
"executionMode": "UNIT_TESTS_ONLY",
"queryPriority": "INTERACTIVE",
"includedTags": [
"test-tag-1",
"test-tag-2"
]
}
}
Inspecter les résultats des tests unitaires
Vous pouvez examiner les différences entre les scripts attendus et réels d'un test unitaire dans Graphique compilé ou dans Exécutions.
Graphique compilé
Pour afficher les scripts réels et attendus d'un test unitaire dans le graphique compilé des actions de workflow, procédez comme suit :
Dans la console Google Cloud , accédez à la page Dataform.
Sélectionnez un dépôt.
Sélectionnez un espace de travail de développement.
Facultatif : Pour afficher les tests unitaires associés aux actions qu'ils testent, au lieu de les afficher en tant que nœuds de graphique indépendants, définissez le paramètre
includeTestsInCompiledGraphsurtruedans le fichierworkflow_settings.yaml:- Sélectionnez le fichier
workflow_settings.yaml. - Ajoutez le code suivant :
includeTestsInCompiledGraph: true- Sélectionnez le fichier
Cliquez sur Graphique compilé.
Dans le graphique compilé, sélectionnez un test unitaire, puis cliquez sur Requête.
Comparez le script SQL réel et le script SQL attendu.
Exécutions
Dans la console Google Cloud , accédez à la page Dataform.
Sélectionnez un dépôt.
Sélectionnez un espace de travail de développement.
Cliquez sur Exécutions, puis sur Afficher les détails à côté du test unitaire sélectionné.
Comparez la requête sur les résultats réels et la requête sur les résultats attendus.
Bonnes pratiques pour les tests unitaires
- Limitez la taille des ensembles de données fictifs
- Conservez les données d'entrée fictives sur moins de 10 lignes pour une compilation plus rapide et un débogage plus facile.
- Spécifier un ordre de ligne explicite
- Ajoutez toujours une clause
ORDER BYà la fois à votre requête d'action et à votre requête de résultat attendu pour garantir un ordre déterministe des lignes lors de l'évaluation. - Caster explicitement les colonnes dans vos instructions fictives
- Le fait de caster explicitement les colonnes dans vos instructions de simulation (par exemple, en utilisant
CAST(100 AS INT64)) permet de maintenir la rigueur des types et d'éviter les erreurs de compilation. - Inclure des scénarios de test avec des valeurs
NULLou manquantes - L'inclusion de cas de test avec des valeurs
NULLou manquantes dans vos requêtes fictives d'entrée garantit que vos instructionsCOALESCE, vos opérations sur les chaînes et vos critères de filtrage gèrent de manière sécurisée les données de production incomplètes ou nulles.
L'exemple de code suivant montre un cas de test NULL :
input "source_customers" {
SELECT 101 AS customer_id, 'Alice' AS name UNION ALL
SELECT 102 AS customer_id, NULL AS name -- Test null handling
}
Étapes suivantes
- Pour en savoir plus sur les types d'assertions, consultez l'API Dataform.
- Pour savoir comment définir des assertions avec JavaScript, consultez Créer des workflows exclusivement avec JavaScript.
- Pour savoir comment exécuter manuellement des workflows, consultez Déclencher manuellement des exécutions.