Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

RegreSQL: regression test per le query SQL

RegreSQL è un regression driver per SQL che, dato un set di query, le esegue di nuovo e confronta l'output con quello precedente
RegreSQL è un regression driver per SQL che, dato un set di query, le esegue di nuovo e confronta l'output con quello precedente
Link copiato negli appunti

Quando pensiamo ai test automatizzati immaginiamo subito unit test e integration test di un'applicazione. Molto più raramente applichiamo la stessa disciplina alle query SQL che, invece, sono spesso il cuore della logica di business e delle performance. RegreSQL nasce esattamente per colmare questo vuoto: è un tool pensato per il regression testing delle query SQL su PostgreSQL e tratta il codice SQL come un vero e proprio “artefatto” da proteggere nel tempo.

Che cos'è RegreSQL

RegreSQL è un “regression driver” per query SQL: dato un set di query, un database in uno stato noto e un insieme di risultati attesi, esegue di nuovo le query e confronta l'output con quello registrato in precedenza. Se qualcosa cambia nei dati, nelle query o nel modo in cui PostgreSQL le esegue, il test fallisce e si ha un alert immediato.

Il tool supporta PostgreSQL ed è scritto in Go, può essere installato sia tramite Homebrew su macOS che con "go install". Ciò lo rende più facile da integrare nelle toolchain.

L'idea di fondo del progetto è la seguente: il codice da testare sono le query SQL del repository e per ogni query viene registrato un result set atteso. Viene poi gestito uno stato di test coerente tramite fixture e il comando "regresql test" riesegue tutto e verifica che i risultati coincidano con quanto atteso.

Installazione e setup

Su macOS si può installare l'applicazione con Homebrew:

brew install regresql

In alternativa, se si usa Go:

go install github.com/boringsql/regresql@latest

Il binario finirà nel "GOPATH/bin", generalmente "~/go/bin", che si dovrà avere nel PATH per richiamare "regresql" da qualsiasi directory. Il primo comando da conoscere è:

regresql init [-C dir]

Esso crea la struttura delle directory e lancia tutte le query SQL trovate nella codebase per generare i primi file. L'opzione "-C" consente di cambiare directory prima dell'esecuzione.

Init, plan, update, test

Il flusso tipico in un progetto potrebbe essere:

  1. "regresql init". Inizializza il progetto, crea la directory "./regresql" e genera la configurazione "regresql.yaml" con la stringa di connessione PostgreSQL e la root da cui cercare i file SQL.
  2. "regresql plan [--run pattern]". Crea i file di piano ("plans") per le query trovate. I file YAML descrivono quali parametri usare nei test per query parametrizzate e possono essere editati per coprire casi specifici.
  3. "regresql update [--run pattern]". Aggiorna i file di expected results ("./regresql/expected/...
  4. "regresql baseline". Genera o aggiorna le baseline dei piani di esecuzione delle query ("EXPLAIN") ed è utile per monitorare le regressioni di performance.
  5. "regresql test [--run pattern] [--format format] [-o output]". Esegue i test confrontando i risultati ("./regresql/out/..") con quelli attesi ("./regresql/expected/.."). Il formato di output può essere: console, pgtap, junit, json o uno specifico per GitHub Actions.

L'opzione "--run" accetta espressioni regolari e permette di lanciare solo un subset di query, ad esempio quelle che contengono “user”, quelle che iniziano per "get" o una specifica per nome.

Come vengono gestite le query SQL

RegreSQL scansiona ricorsivamente un repository alla ricerca di file SQL. Ogni file può contenere una o più query separate da header comment come:

-- name: query_name
-- metadata: key1=value1, key2=value2
SELECT ...;

-- name definisce un identificatore univoco della query nel file. "-- metadata" permette di aggiungere opzioni come:

  • "regresql: notest" per escludere query dai test;
  • "regresql: nobaseline" per saltare la generazione della baseline di "EXPLAIN";
  • "regresql: noseqscanwarn" per sopprimere i warning;
  • "regresql: difffloattolerance:0.01" per definire una tolleranza sulle differenze nei risultati in virgola mobile.

Se il file contiene una sola query si può omettere "-- name": la query verrà nominata automaticamente usando il nome del file senza estensione. Le query possono usare parametri nominali (":name"), posizionali ("$1", "$2"..) o commenti.

Fixture: dati di test dichiarativi

RegreSQL offre un sistema di fixture dichiarative per definire lo stato del database tramite YAML. Si possono usare inoltre dati statici o generatori per popolare tabelle con dati realistici.

fixture: users
description: Test user accounts
cleanup: rollback
data:
 - table: users
 rows:
 - id: 1
 email: test@example.com
 name: Test User

Questa fixture può poi essere referenziata in un test plan. L'applicazione si occuperà di caricarla prima del test e di eseguire il cleanup.

Sono disponibili generatori per sequenze, numeri, stringhe, email, UUID, intervalli di date e molto altro, così come fixture SQL che eseguono script o statement inline. Le fixture possono dipendere l'una dall'altra e si può gestirle da CLI con comandi come "fixtures list", "fixtures validate", "fixtures show", "fixtures apply" e "fixtures deps".

Questo significa poter descrivere scenari complessi (grandi dataset, relazioni..) in modo ripetibile, senza dover scrivere manualmente script di setup per ogni test.

Organizzazione dei file e integrazione nel repository

RegreSQL si appoggia a una struttura di directory creata sotto "./regresql":

  • "regresql.yaml": configurazione principale (stringa di connessione PostgreSQL, root del codice SQL, impostazioni di “plan quality” come tabelle da escludere dai warning.
  • "./regresql/plans/..": per ogni query viene creato un YAML con i parametri di input da usare nei test.
  • "./regresql/expected/..": JSON con i risultati attesi delle query.
  • "./regresql/out/..": JSON con i risultati prodotti durante i test.

È possibile escludere file SQL di migrazione o query temporanee con ".regresignore" o sfruttare la sezione "ignore" in "regresql/regresql.yaml".

Conclusioni

Per gli sviluppatori usare RegreSQL significa poter effettuare il refactoring di query complesse con la sicurezza di non cambiarne il comportamento. Permette inoltre di avere una documentazione delle query principali e di integrare facilmente test SQL nella stessa pipeline dei test applicativi.

Gli amministratori di database possono invece monitorare correttezza e qualità dei piani di esecuzione, standardizzare gli scenari di test tramite fixture e intercettare pattern problematici (ad esempio join inefficienti) con strumenti automatizzati. Il tutto senza basarsi soltanto su analisi di EXPLAIN.

Ti consigliamo anche