Innanzitutto, dobbiamo aggiungere due nuovi pacchetti dbt, aspettative-dbt e dbt-utils, che ci permetterà di fare asserzioni sullo schema dei nostri sorgenti e sui valori accettati.
# packages.ymlpackages:
- package: dbt-labs/dbt_utils
version: 1.1.1
- package: calogica/dbt_expectations
version: 0.8.5
Testare le origini dati
Iniziamo definendo un test contrattuale per la nostra prima fonte. Estraiamo i dati da raw_heightuna tabella che contiene le informazioni sull’altezza degli utenti dell’app palestra.
Concordiamo con i nostri produttori di dati che riceveremo la misurazione dell’altezza, le unità di misura e l’ID utente. Siamo d’accordo sui tipi di dati e sul fatto che solo “cm” e “pollici” sono supportati come unità. Con tutto ciò, possiamo definire il nostro primo contratto nel file YAML sorgente dbt.
Gli elementi costitutivi
Osservando il test precedente, possiamo vedere diverse macro di dbt-unit-testing in uso:
- dbt_expectations.expect_column_values_to_be_of_type: Questa affermazione ci consente di definire il tipo di dati della colonna previsto.
- valori_accettati: Questa affermazione ci consente di definire un elenco dei valori accettati per una colonna specifica.
- dbt_utils.accepted_range: Questa affermazione ci consente di definire un intervallo numerico per una determinata colonna. Nell’esempio, ci aspettavamo che il valore della colonna non fosse inferiore a 0.
- non nullo: Infine, asserzioni integrate come ‘not null’ ci consentono di definire vincoli di colonna.
Utilizzando questi elementi costitutivi, abbiamo aggiunto diversi test per definire le aspettative contrattuali sopra descritte. Notate anche come abbiamo contrassegnato i test come “contract-test-source”. Questo tag ci consente di eseguire tutti i test del contratto in isolamento, sia localmente, sia come vedremo più avanti, nella pipeline CI/CD:
dbt test --select tag:contract-test-source
Abbiamo visto quanto velocemente possiamo creare test di contratto per le fonti della nostra app dbt, ma per quanto riguarda le interfacce pubbliche della nostra pipeline di dati o del nostro prodotto dati?
Come produttori di dati, vogliamo assicurarci di produrre dati secondo le aspettative dei nostri consumatori di dati in modo da poter soddisfare il contratto che abbiamo con loro e rendere la nostra pipeline di dati o il nostro prodotto di dati affidabile e affidabile.
Un modo semplice per garantire il rispetto degli obblighi nei confronti dei consumatori di dati è aggiungere test contrattuali per le nostre interfacce pubbliche.
Dbt ha recentemente rilasciato una nuova funzionalità per i modelli SQL, contratti modelloche permette di definire il contratto per un modello dbt. Mentre costruisci il tuo modello, dbt verificherà che la trasformazione del tuo modello produrrà un set di dati corrispondente al suo contratto, altrimenti non verrà creato.
Vediamolo in azione. Il nostro mercato, indici_di_massa_corporeaproduce una metrica BMI dai dati di misurazione del peso e dell’altezza che otteniamo dalle nostre fonti. Il contratto con il nostro fornitore stabilisce quanto segue:
- Tipi di dati per ogni colonna.
- Gli ID utente non possono essere nulli
- Gli ID utente sono sempre maggiori di 0
Definiamo il contratto del modello body_mass_indexes utilizzando i contratti del modello dbt:
Gli elementi costitutivi
Osservando il file di specifica del modello precedente, possiamo vedere diversi metadati che ci consentono di definire il contratto.
- contratto.applicato: Questa configurazione dice a dbt che vogliamo applicare il contratto ogni volta che viene eseguito il modello.
- tipo di dati: Questa affermazione ci consente di definire il tipo di colonna che prevediamo di produrre una volta eseguito il modello.
- vincoli: Infine, il blocco dei vincoli ci dà la possibilità di definire vincoli utili come quello che una colonna non può essere nulla, impostare chiavi primarie ed espressioni personalizzate. Nell’esempio sopra abbiamo definito un vincolo per dire a dbt che user_id deve essere sempre maggiore di 0. Puoi vedere tutti i vincoli disponibili Qui.
Esiste una differenza tra i test contrattuali che abbiamo definito per le nostre fonti e quelli definiti per i nostri mercati o porti di output quando i contratti vengono verificati e applicati.
I contratti modello vengono applicati quando il modello viene generato dall’esecuzione dbt, mentre i contratti basati sui test dbt vengono applicati quando vengono eseguiti i test dbt.
Se uno dei contratti modello non è soddisfatto, verrà visualizzato un errore quando si esegue ‘dbt run’ con dettagli specifici sull’errore. Puoi vedere un esempio nel seguente output della console di esecuzione dbt.
1 of 4 START sql table model dbt_testing_example.stg_gym_app__height ........... (RUN)
2 of 4 START sql table model dbt_testing_example.stg_gym_app__weight ........... (RUN)
2 of 4 OK created sql table model dbt_testing_example.stg_gym_app__weight ...... (SELECT 4 in 0.88s)
1 of 4 OK created sql table model dbt_testing_example.stg_gym_app__height ...... (SELECT 4 in 0.92s)
3 of 4 START sql table model dbt_testing_example.int_weight_measurements_with_latest_height (RUN)
3 of 4 OK created sql table model dbt_testing_example.int_weight_measurements_with_latest_height (SELECT 4 in 0.96s)
4 of 4 START sql table model dbt_testing_example.body_mass_indexes ............. (RUN)
4 of 4 ERROR creating sql table model dbt_testing_example.body_mass_indexes .... (ERROR in 0.77s)Finished running 4 table models in 0 hours 0 minutes and 6.28 seconds (6.28s).
Completed with 1 error and 0 warnings:
Database Error in model body_mass_indexes (models/marts/body_mass_indexes.sql)
new row for relation "body_mass_indexes__dbt_tmp" violates check constraint
"body_mass_indexes__dbt_tmp_user_id_check1"
DETAIL: Failing row contains (1, 2009-07-01, 82.5, null, null).
compiled Code at target/run/dbt_testing_example/models/marts/body_mass_indexes.sql
Fino ad ora disponiamo di una serie di potenti test contrattuali, ma come e quando li eseguiamo?
Possiamo eseguire test a contratto in due tipi di pipeline.
- Condutture CI/CD
- Pipeline di dati
Ad esempio, è possibile eseguire i test del contratto di origine in base a una pianificazione in a Conduttura CI/CD prendendo di mira le origini dati disponibili in ambienti inferiori come test o stadiazione. È possibile impostare la pipeline in modo che fallisca ogni volta che il contratto non viene rispettato.
Questi fallimenti forniscono informazioni preziose sulle modifiche che violano il contratto introdotte da altri team prima che queste modifiche raggiungano la produzione.
Fonte: towardsdatascience.com