2009-07-10 23 views
16

Qual è il modo migliore per eseguire il test unitario del middleware .NET dipendente dal database? Per esempio. un processo che legge i dati da più database, li manipola e quindi li combina e li scrive in altri database?Test unità Test delle applicazioni .NET basate su database

Le banche dati devono essere riempite con dati statici che vengono in qualche modo ripristinati su ciascuna unità? L'accesso all'intero SQL Server dovrebbe essere in qualche modo deriso? Non è fattibile testare unitamente un'applicazione del genere nel mondo reale?

+1

Penso che i test di interazione funzionerebbero meglio qui – IAdapter

+5

Dato che c'è così tanto interesse in un argomento così semplice e comune, suggerirei che ci sarebbe un enorme mercato per un case study o un libro su questo argomento. Colpisce quasi tutti gli sviluppatori .NET, eppure le informazioni sono lacunose e non provate.Sappiamo quali sono le migliori pratiche, ma in questo scenario come possono essere praticamente implementati i test unitari/beffardi? –

risposta

5

La risposta sta prendendo in giro

Tuttavia il modo per fare questo ho trovato è il seguente.

Separare il DAL in 2 livelli. La parte inferiore esegue semplicemente la lettura e la scrittura atomica nei database: tutti questi oggetti implementano un insieme di interfacce IReadFromDB e IWriteToDB.

Quindi è possibile creare la logica di business di lettura e scrittura in un livello DAL più alto, ma piuttosto fare riferimento agli oggetti che leggeranno e scrivono al database fanno riferimento alle interfacce e utilizzano le proprietà per poter sostituire la funzionalità. Tendo a includere gli oggetti funzionali desiderati nei costruttori in modo che le cose funzionino "fuori dagli schemi", per così dire.

Questo lo renderà un gioco da ragazzi per "scambiare" la funzionalità e quindi per testare unitamente la logica di business.

Per quanto riguarda il test del DB, leggi e scrive ... Non ho trovato un modo che non implichi il lavoro. Di solito uso una stringa di connessione diversa per una copia del database e quindi scrivo il codice di generazione e pulizia dei dati per i test delle unità per lasciare lo stato del db lo stesso di prima e dopo.

Sì, è una perdita di tempo ... tuttavia non rischia di alienare un cliente. Dipende dalle tue priorità.

Qualcun altro ha menzionato il test delle prestazioni. Non lo considererei parte di un test unitario. Solitamente lo faccio con un'imbracatura di test in combinazione con il codice di debug semplicemente perché l'esecuzione di piccole parti è spesso fuorviante - quando si passa all'immagine grande, le parti che sono effettivamente problemi di involucro non sono spesso le parti che il test localizzato avrebbe contrassegnato nella mia esperienza .

2

Penso che la migliore pratica sia proprio quella di prendere in giro tutti gli accessi al database - basta restituire alcuni dati statici predeterminati su chiamata - non è necessario testare il funzionamento dei database - la necessità di testare il comportamento dell'unità. Meno il test dell'unità interagisce con l'esterno, meglio è.

Con il mocking sarete in grado di verificare che la chiamata al database sia valida senza realmente invocarla, quindi è quello che vi serve penso.

+0

Come funzionerebbe in pratica? L'applicazione richiede un campione di dati con cui lavorare. Nessun dato significa che non farà nulla. Quale sarebbe il modo migliore per archiviare questi dati di esempio e renderli disponibili per la funzione da testare. Non penso che i test unitari basati sui dati siano la strada da percorrere (nel caso qualcuno lo suggerisca) poiché riguarda i parametri delle funzioni e dei valori restituiti, piuttosto che l'interazione della funzione con il database. –

+0

Immaginate di avere un metodo readUserData() che richiama una query di database. Basta impostare uno stub su questa query per restituire i dati essenziali e verificare come è stata richiamata quella query e come i dati vengono elaborati dalla tua unità (qual è il risultato del suo lavoro). Ecco come ho capito questo. Ho avuto alcuni esempi nella mia vita usando oggetti Moke ma solo in Python ... –

+0

Guarda la soluzione MrTortoise con livelli separati, è il modo migliore per pensare a come puoi usare l'accesso al database Moke. –

0

Dovresti provare a stratificare il codice in modo da poter prendere in giro il funzionamento delle tue funzioni.

Il livello che ha effettivamente bisogno di comunicare con il database potrebbe utilizzare un sistema di impostazione dei dati e di lavorare con esso all'interno di una transazione, che si ripristinerebbe alla fine del test.

1

Suggerirei di prendere in giro il livello di accesso ai dati. I vantaggi dell'utilizzo di mock in questa istanza includono: 1) i test di unità verranno eseguiti più rapidamente. Se devono fare tutto il lavoro di connessione al db, estraendo dati, ecc., Il costo diventerà costoso. Test costosi = le persone smettono di gestirli/iniziano a perdere fiducia in loro! 2) È possibile testare una vasta gamma di scenari senza dover passare attraverso il fastidio di impostare dati test/statici appropriati che devono essere sempre presenti nel DB prima dell'inizio dei test. 3) togliendo il sistema db esterno dall'equazione significa che stai testando solo il codice .NET che vuoi testare. Nessuna dipendenza esterna.

Si potrebbe avere un livello di accesso ai dati che fa pura interazione con db, e poi si prende in giro. In alternativa, usa mock SqlCommands ecc nel tuo codice .NET.

1

Penso che dovresti separare le tue preoccupazioni in diversi tipi di test.

  • Test di unità di scrittura per la logica di manipolazione dei dati implementata in .NET. O prendi in giro i database o separa completamente la logica di massaggio dei dati dalle informazioni di accesso ai dati e dai semplicemente la tua routine di manipolazione dei dati con i dati di input precotti.
  • Creare un test di integrazione che esercita l'intero flusso di dati. Questo test dovrebbe anche essere automatizzato. Impostare i database di origine e di destinazione (dallo script DB o dal backup del database) in uno stato noto, eseguire la logica di manipolazione dei dati, quindi controllare i risultati.
  • Si potrebbe anche voler creare prestazioni e stress test se si gestiscono molti dati. È possibile impostare un database (s) nello stesso modo in cui è stato eseguito nel test di integrazione, generare un gruppo di dati di test, eseguire il componente e controllare entrambi i tempi di esecuzione o completarlo (ad esempio, nessun problema di concorenza, deadlock, ecc.)
0

Vorrei astrarre il livello di accesso ai dati e quindi deriderlo. Con il mocking sarai in grado di aumentare la copertura del codice dei tuoi test. Inoltre impedirà l'idea di 'Test Cancer' che avverrà effettuando chiamate costose su rete/file system/database perché la gente smetterà di eseguirli.

Si dovrebbero eseguire alcuni test che chiamano al database ma dovrebbero essere il più limitati possibile.

1

ho due metodi per testare il codice unità che ha dipendenze database:

  • oggetti fittizi cioè TypeMock
  • script personalizzati SQL esecuzione in TestInitialise() e TestCleanup) subs (.

Con TypeMock, posso dati del database falsi che entrano in mio codice, che mi aiuta a correre le mie prove, senza doversi preoccupare di ripulire il database o il ripristino dei backup ecc Io uso beffardo per il codice di test al di fuori della base di dati logica, ma richiede ancora dati falsi dal database.

Con script SQL personalizzati, è possibile eseguire comandi SQL sul sottotitolo TestInitialise() e, al termine del test dell'unità, ho eseguito il cleanup SQL sul sottotitolo TestCleanup(). Io uso questo metodo per testare il codice in cui la logica del database è più complicata. Ad esempio, potrei aver bisogno di inserire alcune righe in tabelle che aiuteranno a testare il codice. Quindi sul TestCleanup() avrò i miei comandi SQL di cancellazione che rimuovono tutti i record che sono stati inseriti tramite il sub TestInitialise().

+0

Mi piacciono entrambe le opzioni. TypeMock (e simili) sembrano offrire la possibilità di aggiungere ciò che voglio testare unitamente a modifiche significative del codice o dell'architettura. Tuttavia mi sento di sentire se avessi fatto 'giusto' non avrei dovuto fare affidamento su questi costosi strumenti di terze parti. Esattamente ciò che 'giusto' rimane aperto alla discussione. –

0

Nel mio lavoro usiamo Nunit e Typemock per il nostro test dell'unità. Il fatto che non abbiamo bisogno di cambiare il nostro codice per i test è un grande vantaggio. Prendere in giro il DAL è la strada da percorrere.