Test unitari di procedure memorizzate


44

Lo sto prendendo in considerazione da molto tempo ormai.

La domanda di base è: come testare le procedure memorizzate?

Vedo che posso impostare unità di test relativamente facilmente per funzioni in senso classico (intendo che ottengono zero o più argomenti e restituiscono un valore). Ma se considero un esempio di vita reale di una procedura apparentemente semplice che inserisce una riga da qualche parte, con alcuni trigger che fanno questo e che prima o dopo l'inserimento, persino definire i confini di una 'unità' è abbastanza difficile. Dovrei testare solo lo INSERTstesso? È abbastanza semplice, credo, con un valore relativamente basso. Devo testare il risultato dell'intera catena di eventi? A parte la domanda se si tratti di un test unitario o meno, progettare un test adatto può essere un lavoro piuttosto faticoso con molti altri punti interrogativi che sorgono sulla strada.

E poi arriva il problema della costante modifica dei dati. Nel caso in cui UPDATEcolpisca più di poche righe, ogni riga potenzialmente interessata deve essere inclusa in qualche modo nei casi di test. Ulteriori difficoltà con DELETEs e così via e così via.

Quindi come testate le vostre procedure memorizzate? C'è una soglia di complessità in cui diventa completamente senza speranza? Quali risorse sono necessarie per la manutenzione?

MODIFICA Un'altra piccola domanda, basata sulla risposta di AlexKuznetsov: O c'è una soglia sotto la quale è completamente inutile?

Risposte:


32

Lo facciamo da quasi cinque anni e pensiamo che testare esplicitamente le modifiche sia sicuramente fattibile, ma è piuttosto lento. Inoltre, non possiamo facilmente eseguire tali test contemporaneamente da più connessioni, a meno che non utilizziamo database separati. Invece, dovremmo testare implicitamente le modifiche: le usiamo per creare almeno alcuni dei dati del test e verificare che i nostri risultati di restituzione attesi siano selezionati.

Ho scritto un articolo intitolato Chiudi quelle scappatoie: lezioni apprese da Unit Testing T-SQL , nonché alcuni post sul blog

Per quanto riguarda la tua domanda "Esiste una soglia di complessità in cui diventa completamente senza speranza?", I moduli complessi hanno bisogno di test molto più di quelli semplici.

Per semplificare la manutenzione, generiamo i risultati previsti e li memorizziamo in file separati, il che fa una grande differenza.


15

Sì, dovresti testare l'intera catena di eventi come un'unità. Quindi, nel tuo esempio con una procedura che si inserisce in una tabella e provoca l'attivazione di più trigger, è necessario scrivere test unitari che valutano la procedura per vari input. Ogni test unitario dovrebbe superare o fallire a seconda che restituisca i valori corretti, cambi correttamente lo stato delle tabelle, crei l'e-mail corretta e persino invii i pacchetti di rete corretti se è progettato per fare una cosa del genere. In breve, tutti gli effetti dell'unità devono essere verificati.

Hai ragione, che la progettazione di unit test richiede un po 'di lavoro, ma la maggior parte di quel lavoro deve essere fatto per testare manualmente l'unità, stai solo salvando il lavoro necessario per testare l'unità in modo che, quando in futuro viene effettuata una modifica, il test può essere altrettanto completo e significativamente più semplice.

La modifica dei dati rende i test più difficili, ma non rende i test meno importanti e aumenta effettivamente il valore dei test unitari poiché la maggior parte delle difficoltà deve essere considerata solo una volta anziché ogni volta che viene apportata una modifica all'unità. Set di dati salvati, inserimenti / aggiornamenti / eliminazioni che fanno parte dell'installazione / smontaggio e operazioni con ambito ristretto possono essere utilizzati per semplificare tutto ciò. Poiché la domanda non è specifica del database, i dettagli varieranno.

Non esiste una soglia di complessità nella fascia alta o bassa che dovrebbe impedirti di eseguire test o test unitari. Considera queste domande:

  1. Scrivi sempre un codice privo di bug?
  2. Le piccole unità sono sempre prive di bug?
  3. Va bene che un'unità di grandi dimensioni abbia un bug?
  4. Quanti bug ci vogliono per causare un disastro?

Supponiamo di iniziare un nuovo lavoro e di avere il compito di eseguire un'ottimizzazione su una piccola funzione utilizzata in molti luoghi. L'intera domanda è stata scritta e gestita da un dipendente che nessuno ricorda nemmeno. Le unità hanno documentazione che descrive il normale comportamento previsto, ma poco altro. Quale di questi preferiresti trovare?

  • Nessun test unitario in qualsiasi parte dell'applicazione. Dopo aver apportato la modifica, è possibile eseguire alcuni test manuali sull'unità stessa per assicurarsi che restituisca ancora i valori previsti nella documentazione. Puoi quindi distribuirlo alla produzione, incrociare le dita e sperare che funzioni (dopotutto, scrivi sempre codice privo di bug e un'ottimizzazione in un'unità non potrebbe mai influire su un'altra) o impiegare molto tempo a imparare come l'intera applicazione funziona in modo da poter testare manualmente ogni unità direttamente o indirettamente.
  • Test unitari in tutta l'applicazione eseguiti automaticamente ogni giorno o su richiesta. Controllano non solo i normali valori di input e la loro risposta prevista, ma anche valori anomali e le eccezioni previste che vengono sollevate. Apportate la modifica ed eseguite la suite di test unitari per l'applicazione, vedendo immediatamente che altre tre unità non restituiscono più i risultati previsti. Due di questi sono benigni, quindi devi modificare i test unitari per renderlo conto. Il terzo richiede un altro leggero aggiustamento e un nuovo test unitario. Dopo aver apportato le modifiche, l'intera suite di test ha esito positivo e si implementa la modifica con sicurezza.

1
In primo luogo, grazie per la risposta: non mi aspettavo ulteriori progressi su questa domanda ... In secondo luogo, devo ammettere che hai ragione sulle semplici operazioni: anche un INSERT a due colonne può produrre un bug. Se è scritto in modo che l'ordine delle colonne possa essere confrontato con gli argomenti, allora potrebbe essere OK, ma poi hai ragione, di nuovo: probabilmente è meglio mantenere l'intera app sotto il regime di test.
dezso

@dezso È una grande domanda e un concetto che richiede molta più esposizione nel mondo del Database.
Leigh Riffel,

"dovresti testare l'intera catena di eventi come un'unità": questa è la cosa più intuitiva che potresti dire. Non è un'unità se è così. Stai facendo test di integrazione
Joe Phillips,

@Joe Philips: chiamalo come preferisci, assicurandoti che una procedura che esegua un inserimento e attivi alcuni trigger faccia ciò di cui si suppone abbia bisogno per avere test automatici.
Leigh Riffel,

8

Per PostgreSQL, controlla pgTAP :

pgTAP è una suite di funzioni di database che semplifica la scrittura di test unit che emettono TAP in script psql o funzioni di test in stile xUnit.


Visto che, grazie. Qualcuno ha esperienza con esso?
dezso,

Sì, al giorno d'oggi un bel po 'di gente. Iscriviti alla mailing list se hai domande.
teoria del

6

Se preferisci che i test delle procedure memorizzate vengano eseguiti interamente su SQL, dai un'occhiata a http://tsqlt.org/

È compatibile con MS SQL 2005 SP2 e versioni successive e il vantaggio è che gli sviluppatori non devono conoscere C # o un'altra lingua per implementare i test.

Ci sono anche strutture per fare tabelle e viste simulate per aiutarti a raggiungere una suite di test rieseguibile.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.