2009-04-08 36 views
24

C'è un articolo su www.sqlservercentral.com sull'unità che verifica il tuo SQL.L'unità sta testando il tuo SQL prendendo TDD troppo lontano?

Il TDD Guy in me ha detto di sì, possiamo testare il materiale del database.

Il System Architect in me ha detto, quale logica stiamo testando? Non ci dovrebbe essere alcuna logica nel database, l'unica cosa che dovresti fare nel database è selezionare, aggiornare o inserire.

Quindi, se si sente la necessità di testare l'unità SQL, si sta solo veramente approfondendo, essendo eccessivamente pragmatici, o è un segno di odore di progettazione?

risposta

10

Sono d'accordo con il System Architect, troppa logica aziendale si sta facendo strada nei database in questi giorni.

+0

Sono d'accordo, un database idealmente dovrebbe solo memorizzare dati e logica per preservare l'integrità dei dati. –

+0

@Pop - ma la "logica per preservare l'integrità dei dati" è il problema qui, non è vero? Certamente metto alla prova le mie abilità innescate e i miei vincoli, anche se non faccio TDD con loro. – tvanfosson

+11

Nel mondo ideale maybee, ma alcune funzioni di business funzionano con una grande quantità di dati. Quindi inviare i dati al client, elaborare sul client e inviare i dati è troppo inefficace, è necessario spostare questa funzionalità nel database. – TcKs

1

Penso che sia un po 'eccessivo. Suppongo che potresti farlo e mettere i test in una categoria speciale in modo che non siano in esecuzione su ogni build, forse solo al momento del check-in ed eseguito sul server. In genere con tutti i test unitari non si desidera alcuna dipendenza esterna.

11

L'SQL contiene logica. Ad esempio, la condizione booleana controlla nella clausola "WHERE". Riesci a pensare a modi in cui l'SQL potrebbe essere sbagliato? In tal caso, avrebbe senso testare l'SQL, per garantire che questi errori non fossero presenti?

(Ad esempio, alcuni programmatori stupidi, come me, potrebbero digitare accidentalmente "WHILE" invece di "WHERE" nel mio commento sopra! ... come ho fatto io, ma in seguito l'ho corretto. Quindi dove sono i miei test stackoverflow ?!? ;-)

+1

"while"? intendevi "dove"? –

+0

Sì. Fisso. Grazie! –

4

Questo problema è molto dibattuto. Se chiedi a un DBA, penseranno che sia la cosa migliore del mondo per far sì che tutte le tue app utilizzino procedure memorizzate predefinite. Quei giorni stanno arrivando alla fine, con Hibernate e LINQ che guadagnano popolarità, puoi davvero usare il database come repository di informazioni e far sì che il tuo livello di accesso ai dati elabori tutte le richieste. Penso che LINQ possa fare tutto per te in MS SQL tranne le ricerche full-text. Per quanto riguarda la differenza di prestazioni tra SPROC e LINQ, è trascurabile. Il mio voto non è il codice nel database, tutto il codice nel livello di accesso ai dati yoru e ho provato per questo.

+0

Ci sono alcune cose che LINQ non può fare anche - i vincoli di unicità, per esempio, sono meglio lasciati al DB.Come regola generale, non uso più SPROCS, ma faccio ancora un uso massiccio di indici, vincoli e alcuni trigger unici per fare cose che sono più facili nel DB. – tvanfosson

+1

"Se chiedi a un DBA, penseranno che sia la cosa migliore del mondo per far sì che tutte le tue app usino stored procedure predefinite" Logicamente sì ... "Quei giorni però stanno arrivando alla fine" in poche parole. No. – CaRDiaK

+0

Come ho detto, molto dibattuto. Il database è un archivio dati, indici e contrappesi sono ottimi per mantenere l'integrità dei dati e accelerare le richieste. Questi tipi di cose non richiedono test unitari. Ci sarà sempre anche il codice nel DB, se dovrebbe essere lì o no è in conflitto. –

3

Dipende dall'architettura del database. Se hai solo tabelle e viste, penso che i test unitari non siano necessari, perché ogni (o la maggior parte) dei bug verrà catturato durante il test dell'unità nell'applicazione.

Ma se si dispone di funzioni complesse, stored procedure, trigger ecc., Allora ci sono molti punti in cui può essere un bug e il test dell'unità di applicazione non li copre.

1

Non faccio TDD direttamente nel mio database, ma ci sono molte opportunità in cui è valido inserire "logica" nel database. Vincoli, valori predefiniti (sì, so che è anche un vincolo), trigger, ecc. Spesso questi sono il modo migliore per implementare alcune logiche di business E garantire la coerenza del database. La maggior parte delle volte sono in grado di convincermi della correttezza con alcuni test manuali e lasciarlo, ma potrei vedere dove qualcuno potrebbe voler fare TDD con questo.

EDIT:

Per esempio, userò un valore predefinito su inserto e un trigger su aggiornamento per impostare i campi "L'ultima volta aggiornato" a inserimento/aggiornamento. In LINQ imposterò la colonna come valore generato automaticamente e la renderò di sola lettura. Per me è più semplice dell'aggiunta di un gestore di eventi PropertyChanged per assicurarmi che ogni volta che viene modificato un campo sull'entità, venga modificata anche l'ultima volta aggiornata. Lo collaudo? Certo, ma manualmente e dopo il fatto anche se io preferisco fortemente TDD per la maggior parte delle cose.

0

Finché la clausola WHERE non è vuota, è necessario testarla.

Qui utilizziamo l'API Criteri di NHibernate per interrogare il database. Tuttavia, abbiamo messo semplici test unitari per salvaguardare il livello di accesso ai dati. Considera questo:

public IList<Book> GetBorrowedBooks(User user); 

In primo luogo, può sembrare sciocco. Ma per una situazione così semplice, abbiamo a che fare con almeno 3 oggetti modello: Book, User, Borrow e forse Return. Qualsiasi tentativo di modificare una delle 3 (o più) classi potrebbe infrangere il codice.

Qual è il costo? Scrivere i test in questo esempio richiede meno di 20 minuti, immagino. Con l'aiuto della categoria in NUnit, i test delle unità di accesso ai dati possono essere configurati per l'esecuzione notturna, mentre altri test possono essere eseguiti su ogni commit. I test delle unità di accesso ai dati lenti non danneggiano e sono salvavita.

1

Non so perché quando raggiungiamo il livello db tutte le buone pratiche dovrebbero andare alla finestra. Se c'è una logica in questo strato è doppiamente importante. C'è un ottimo strumento costruito sopra Fitnesse chiamato dbfit che sembra togliere tutto il dolore dall'unità che sta testando il dblayer. Se sei interessato, dovresti dare un'occhiata.

5

distinguere tra unit test/spec test di integrazione/spec.

Se le classi hanno entrambi, si sta violando un principio di suono: Separation of Concerns.

I test devono essere chiaramente definiti tra i test unitari per testare unità POCO/POJO ignoranti persistenti come entità, servizi e test di integrazione. Che sono per testare dove la tua applicazione colpisce il metallo.

test di integrazione dovrebbero verificare la persistenza, come repository e unità di esecuzione di lavoro per il vostro meccanismo di persistenza (RBDMS), Active Directory, Exchange, File System e-mail, ecc

Se il caso d'uso richiede l'una prova completa punto di integrazione, che utilizza un trigger quindi verifica il comportamento non esplicitamente il trigger. In futuro potresti scegliere di non utilizzare un trigger e utilizzare invece un intercettore ORM o AoP.

21

Nella maggior parte dei progetti viventi, il database presenta una certa quantità di flusso tra le tappe del progetto. Tabelle e colonne vengono create, eliminate o modificate. Le tabelle di ricerca sono aggiornate. E potresti testare più istanze del database, quindi è bene avere una convalida dello stato dei metadati e dei dati nel database, come parte dei test di regressione.

Ci sono diversi casi in cui vorrei suggerire la prova di un database:

  • Tabelle & vista: verificare le tabelle e le viste che ci si aspetta di esistere. Verifica che queste tabelle e viste contengano le colonne che ti aspetti. È inoltre possibile verificare che tabelle, viste o colonne eliminate in questo milestone siano effettivamente assenti.

  • Vincoli: provare ad eseguire modifiche ai dati che devono essere rifiutate. I vincoli dovrebbero impedire queste modifiche. Puoi evitare errori successivi se trovi casi in cui i vincoli non funzionano.

  • Trigger: come per i vincoli, e anche i trigger possono essere utilizzati per effetti a cascata, o per trasformare valori, ecc. Verificare questi percorsi logici.

  • Stored procedure: supporto la cautela nel mettere troppa logica nel database, quando la logica è più facilmente sviluppata, sottoposta a debug e mantenuta nel livello dell'applicazione. Ma ci sono casi in cui ci sono validi motivi per usare proc memorizzati. Spesso si vede un collo di bottiglia delle prestazioni risolto inserendo una logica complessa nel database. Quindi i proc memorizzati non stanno andando via completamente, e testarli è una buona idea.

  • Dati di bootstrap: le tabelle di ricerca sono un esempio di dati che devono essere presenti anche in un database "vuoto". Ci possono essere altri esempi. Verificare che il database contenga i dati richiesti.

  • Query: il codice dell'applicazione è associato a query SQL. Provali per la corretta funzionalità e anche per le prestazioni. Soprattutto le prestazioni - perché la stessa query può funzionare bene un giorno e diventare un collo di bottiglia il giorno successivo, poiché il volume dei dati cambia, gli indici crescono squilibrati, ecc.

  • Classi ORM: come trigger, classi ORM nell'applicazione può contenere la logica per convalidare, trasformare o monitorare le operazioni del database. Questi dovrebbero essere testati.

Questi test potrebbero non essere definiti con precisione "test dell'unità". Il test unitario è un tipo specifico di test in cui ogni test è indipendente da altri test e si prova a testare piccole unità di codice isolate. Direi che testare il database come descritto sopra è un esempio della funzionalità testing.

2

L'architetto di sistema è corretto. Non ci dovrebbe essere l'inserimento di business logic nel tuo database e quindi non sei davvero un test unitario.

0

DbFit è un ottimo strumento per il test dell'unità del database. Penso che sia saggio usare TDD con SQL perché, dopo tutto, è un linguaggio dichiarativo con ramificazioni condizionali, funzioni aggregate e così via. Senza test sul posto, come puoi essere sicuro di ottenere il risultato desiderato?

Problemi correlati