Nell’articolo precedente, il primo di questa serie, abbiamo descritto che cosa è lo Unit Test e perché è importante prevederlo anche durante lo sviluppo di soluzioni database con T-SQL. In questo secondo articolo descriveremo come installare il framework tSQLt e faremo una breve introduzione a SQL Test, il tool di Red-Gate che semplifica la gestione e l’esecuzione dei test in SQL Server. Descriveremo infine come avviene l’esecuzione di un test case.
Installazione di tSQLt
L’installazione del framework è molto semplice, puntate il vostro browser qui e troverete la pagina Quick Start dalla quale potrete eseguire il download del file .zip che contiene gli script .sql per l’installazione (la versione di tSQLt disponibile durante la stesura di questo articolo è la V1.0.7597.5637, contenuta nel file tSQLt_V1.0.7597.5637.zip).
tSQLt richiede l’abilitazione di SQL CRL nell’istanza SQL di sviluppo che userete per la scrittura e l’esecuzione dei test. Per abilitare SQL CLR potete eseguire il comando contenuto nel file SetClrEnabled.sql presente all’interno dello zip. Poiché normalmente non avremmo Unit Test in ambiente di produzione, questo non introduce un requisito sul server di produzione, tSQLt richiede che SQL CLR sia abilitato sul server di sviluppo.
All’interno dello zip troverete anche il file Example.sql e con lo script contenuto all’interno potrete creare il database di esempio tSQLt_Example. tSQLt registra i test all’interno di uno schema dedicato. Una buona pratica è quella di creare una “classe” tSQLt per ogni entità che si desidera testare in modo separato. All’interno del database tSQLt_Example troverete lo schema AcceleratorTests che contiene i singoli test sotto forma di stored procedure. Il nome di ogni stored procedure di test dovrà iniziare con la parola “test”, questa naming convention indica a tSQLt che la stored procedure è in realtà un test.
I test possono essere eseguiti in due modi:
- Esecuzione di tutti i test all’interno del database
- Esecuzione di test specifici o classi di test
Per eseguire tutti i test presenti all’interno del database si deve utilizzare la stored procedure tSQLt.RunAll, per eseguire test specifici la stored procedure tSQLt.RunTest e per eseguire classi di test la SP tSQLt.RunTestClass. Se eseguiamo tutti i test di esempio nel database tSQLt_Example otterremo il seguente output nel quale si osserva il superamento di tutti i test ad eccezione di uno: [AcceleratorTests].[test ready for experimentation if 2 particles].
(0 rows affected)
[AcceleratorTests].[test ready for experimentation if 2 particles] failed: (Failure) Expected: <1> but was: <0>
+----------------------+
|Test Execution Summary|
+----------------------+
|No|Test Case Name |Dur(ms)|Result |
+--+----------------------------------------------------------------------------------------------------------+-------+-------+
|1 |[AcceleratorTests].[test a particle is included only if it fits inside the boundaries of the rectangle] | 1170|Success|
|2 |[AcceleratorTests].[test a particle within the rectangle is returned with an Id, Point Location and Value]| 33|Success|
|3 |[AcceleratorTests].[test a particle within the rectangle is returned] | 30|Success|
|4 |[AcceleratorTests].[test email is not sent if we detected something other than higgs-boson] | 63|Success|
|5 |[AcceleratorTests].[test email is sent if we detected a higgs-boson] | 30|Success|
|6 |[AcceleratorTests].[test foreign key is not violated if Particle color is in Color table] | 127|Success|
|7 |[AcceleratorTests].[test foreign key violated if Particle color is not in Color table] | 47|Success|
|8 |[AcceleratorTests].[test no particles are in a rectangle when there are no particles in the table] | 13|Success|
|9 |[AcceleratorTests].[test status message includes the number of particles] | 0|Success|
|10|[AcceleratorTests].[test we are not ready for experimentation if there is only 1 particle] | 16|Success|
|11|[AcceleratorTests].[test ready for experimentation if 2 particles] | 17|Failure|
-------------------------------------------------------------------------------
Msg 50000, Level 16, State 10, Line 1
Test Case Summary: 11 test case(s) executed, 10 succeeded, 1 failed, 0 errored.
-------------------------------------------------------------------------------
Completion time: 2020-11-07T16:50:55.3525708+01:00
Per ottenere informazioni sulla versione di tSQLt installata si può utilizzare la funzione tSQLt.Info() che restituirà, in forma tabellare, un output simile a quello riportato di seguito:
Version ClrVersion ClrSigningKey SqlVersion SqlBuild SqlEdition
-------------- ----------------- -------------------- ------------ ---------- ---------------------------
1.0.5873.27393 1.0.5873.27393 0x7722217D36028E4C 14.00 2027.20 Developer Edition (64-bit)
Poiché tSQLt è installato per database, DB diversi sullo stesso server possono eseguire versioni diverse di tSQLt, tuttavia il mio consiglio è quello di standardizzare una versione unica di tSQLt per evitare di avere diverse funzionalità del framework in diversi database.
SQL Test di Red-Gate
Dopo aver eseguito installazione e impostazione di tSQLt, è possibile eseguire i test del vostro codice T-SQL in qualsiasi momento.. ovviamente dopo aver scritto i test case 🙂
La scrittura delle unit di test, a volte, purtroppo, è vista come una perdita di tempo e l’incertezza su come scriverle e da dove iniziare può rappresentare una barriera nella realizzazione sistematica dei test per ogni soluzione database.
SQL Test di Red-Gate fornisce una bella interfaccia utente e alcune facility per lo sviluppo di unit test in T-SQL; è integrato in SQL Server Management Studio e facilita la gestione, l’esecuzione ed il monitoring dei risultati dei test SQL. SQL Test fornisce la possibilità di creare un nuovo test, porrà automaticamente la parola “test” all’inizio del nome della stored procedure in modo che quest’ultima venga riconosciuta da tSQLt come stored procedure di test. Penso che questo strumento sia utile anche come promemoria visivo per ricordare a chi sviluppa codice T-SQL che la realizzazione di unit test rappresenta una parte del lavoro di sviluppo.
SQL Test è indipendente dal framework tSQLt installato nel DB e quindi non è neppure dipendente da una versione specifica di tSQLt. E’ possibile provare SQL Test scaricandolo dal portale red-gate a questo link.
Come avviene l’esecuzione di un test con tSQLt
È giunto il momento di descrivere com’è strutturato un test. Avrete già intuito che ogni test è rappresentato da una stored procedure che dovrà contenere tre parti note con il nome di Arrange, Act e Assert!
Nella sezione Arrange dovrà essere allestita la “scena” del nostro test. Attività tipiche eseguite in questa sezione sono la preparazione dei dati su cui eseguire il test e l’isolamento da eventuali dipendenze esterne (tabelle correlate, trigger, stored procedure ecc..). In questa fase verrà allestito il risultato atteso dal test. La complessità della sezione Arrange è direttamente proporzionale alla complessità del test stesso.
Nella sezione Act verrà eseguito il system under test (SUT) ed acquisito l’output come risultato.
Nella sezione Assert il risultato atteso verrà confrontato con il risultato ottenuto, il test fallirà oppure avrà esito positivo in funzione di questo confronto. Il test avrà esito positivo se il risultato atteso sarà uguale a quello ottenuto dall’esecuzione del system under test (SUT).
Quando eseguiamo un test attraverso tSQLt il framework traccia il test in esecuzione e avvia una transazione dedicata; se presente verrà eseguita la procedura di configurazione per la classe di test e immediatamente dopo il test verrà portato in esecuzione. Al termine del test il framework tSQLt eseguirà il rollback della transazione di prova che porterà il database allo stato in cui era prima dell’inizio del test. I risultati verranno conservati all’interno della tabella tSQLt.TestResult. Quando eseguiamo tutti i test di una classe il processo appena descritto verrà iterato per ogni test nella classe. L’ordine in cui vengono eseguiti i test deve essere irrilevante, il database verrà riportato allo stato iniziale prima dell’inizio della successiva transazione di test. L’esecuzione di tutti i test nel database vedrà l’iterazione del processo per tutte le classi di test.
Nel prossimo articolo verrà descritto come scrivere la prima unit test, nel frattempo se volete approfondire l’argomento, vi consiglio di guardare il video dell’amico Alessandro Alpi:
Buon divertimento!