Qual è il modo migliore per organizzare i nostri test unitari

16

Abbiamo accumulato un numero considerevole di test unitari per il nostro programma principale nel corso degli anni. Molte migliaia. Il problema è che non abbiamo una chiara idea di quali test abbiamo perché ce ne sono così tanti. E questo è un problema perché non sappiamo dove siamo deboli nei test (o dove abbiamo duplicati).

La nostra app è un motore di segnalazione. Quindi puoi avere un template che viene usato per testare l'analisi (leggiamo tutte le proprietà della tabella), unendo i dati (abbiamo mantenuto le proprietà corrette della tabella nell'unione), formattando la pagina finale (la tabella è posizionata correttamente nella pagina ), e / o il formato di output (il file DOCX creato è corretto).

Aggiungi a questo ciò che dobbiamo testare. Prendi il padding attorno a una cella di tabella (usiamo Word, Excel e PowerPoint per la progettazione del report). Dobbiamo testare il padding attraverso l'interruzione di pagina, per un tavolo all'interno di una cella, celle unite verticalmente, celle unite orizzontalmente, una verticale & cella unita orizzontalmente che contiene una tabella con un & verticale celle unite orizzontalmente nella tabella interna, in cui la tabella si rompe su una pagina.

Quindi in quale categoria va il test? Riempimento della tabella, interruzioni di pagina, celle nidificate, celle unite verticalmente, celle unite orizzontalmente o qualcos'altro?

E come possiamo documentare queste categorie, nominare i test unitari, ecc.?

Aggiornamento: un numero di persone ha suggerito di utilizzare gli strumenti di copertura per verificare che abbiamo una copertura completa. Sfortunatamente questo è di uso limitato nel nostro caso perché i bug tendono a essere dovuti a combinazioni specifiche, quindi è il codice che è stato testato, ma non in quella combinazione.

Ad esempio, ieri abbiamo avuto un cliente che ha avviato un segnalibro Word alla fine di un ciclo forEach nel relativo modello (un documento Word) e lo ha terminato all'inizio del ciclo forEach successivo. Questo codice usa tutti i test unitari contro di esso, ma non avevamo pensato alla combinazione di un modello che espandeva un segnalibro che iniziava ad essere avviato 25 volte, quindi è stato terminato 10 volte (i due cicli di Each avevano un diverso numero di righe). / p>     

posta David Thielen 04.10.2011 - 09:35
fonte

5 risposte

11

Generalmente, tendo a rispecchiare l'albero dei sorgenti per i miei test unitari. Quindi, se avessi src / lib / fubar, avrei un test / lib / fubar che contiene i test unitari per fubar.

Tuttavia, ciò che sembra descrivere sono test più funzionali. In tal caso, avrei una tabella multidimensionale che elencasse tutte le possibili condizioni. Quindi, quelli che non hanno test sono privi di senso o necessitano di un nuovo test. Puoi, ovviamente, inserirli in serie di test.

    
risposta data 04.10.2011 - 09:52
fonte
6

La struttura più comune sembra essere il src e il test mirror directory.

src/module/class
test/module/class_test

Tuttavia, c'è una struttura alternativa che ho visto che ora ritengo sia migliore.

src/module/class
src/module/class_test

Dato che il test unitario tende a rispecchiare la classe che stanno testando, posizionandoli nella stessa directory offre un accesso molto più facile ai file in modo da poter lavorare su entrambi i lati.

    
risposta data 29.01.2015 - 19:39
fonte
5

In .NET, tendo a rispecchiare, o almeno approssimare, la struttura dello spazio dei nomi per il codice sorgente nei progetti di test, al di sotto di uno spazio dei nomi master "Tests.Unit" o "Tests.Integration". Tutti i test unitari vanno in un unico progetto, con la struttura di base del codice sorgente replicata come cartelle all'interno del progetto. Lo stesso per i test di integrazione. Quindi, una soluzione semplice per un progetto potrebbe essere simile a questa:

Solution
   MyProduct.Project1 (Project)
      Folder1 (Folder)
         ClassAA (Class def)
         ...
      Folder2
         ClassAB
         ...
      ClassAC
      ...
   MyProduct.Project2
      Folder1
         ClassBA
         ...
      ClassBB
      ...
   ...
   MyProduct.Tests.Unit
      Project1
         Folder1
            ClassAATests
            ClassAATests2 (possibly a different fixture setup)
         Folder2
            ClassABTests
         ClassACTests
      Project2
         Folder1
            ClassBATests
         ClassBBTests
      ...
   MyProduct.Tests.Integration
      Project1 (a folder named similarly to the project)
         Folder1 (replicate the folders/namespaces for that project beneath)
            ClassAATests
         Folder2
            ClassABTests
         ClassACTests
      Project2
         Folder1
            ClassBATests
         ClassBBTests

Per qualsiasi AAT o AEET codificati con un framework di test unitario, questo cambia un po '; solitamente questi test rispecchiano una serie di passaggi, che testeranno la funzionalità di un nuovo caso d'uso o storia. Solitamente strutturo questi test in un progetto MyProduct.Tests.Acceptance come tale, con test per ogni storia, eventualmente raggruppati per pietra miliare o storia "epica" a cui apparteneva la storia in fase di sviluppo. Tuttavia, questi sono in realtà solo test di uber-integrazione, quindi se preferisci strutturare i test in un modo più orientato agli oggetti anziché orientato alla storia non hai nemmeno bisogno di un MyProduct.Tests.Acceptance o un progetto simile; è sufficiente lanciarlo in MyProduct.Tests.Integration nell'ambito dello scopo dell'oggetto di livello più alto in prova.

    
risposta data 04.10.2011 - 19:09
fonte
3

Non c'è motivo per un test unitario di essere solo in una categoria. Tutti i principali toolkit di test unitario supportano la creazione di suite di test , che raggruppano i test per una particolare categoria. Quando una particolare area di codice è stata cambiata, lo sviluppatore dovrebbe prima eseguire quella suite e spesso vedere cosa si è rotto. Quando un test riguarda il riempimento di e interrompe e nidificandolo, inseriscilo in tutte e tre le suite.

Detto questo, il punto dei test unitari è di eseguirli continuamente, cioè dovrebbero essere piccoli e abbastanza veloci da poter essere eseguiti tutti prima di eseguire qualsiasi codice. In altre parole, non importa quale sia la categoria di un test, dovrebbe essere eseguito prima di commetterlo comunque. Le suite sono in realtà solo una stampella che usi se per qualche ragione non puoi scrivere test che siano veloci come dovrebbero.

Per quanto riguarda la copertura, ci sono strumenti di copertura molto buoni che ti dicono quale percentuale di linee sono state effettivamente esercitate eseguendo i tuoi test - questo è un ovvio puntatore a che tipo di test ti manca ancora.

Per quanto riguarda la denominazione, non vi è alcun valore particolare nello sforzo di spesa sui nomi dei test unitari. Tutto quello che vuoi sentire dai tuoi test è "5235 di 5235 test passati". Quando un test fallisce, ciò che leggi non è il suo nome, ma il messaggio , ad es. la stringa in assert() che implementa la tua critrion di successo. Il messaggio dovrebbe essere sufficientemente informativo da avere un'idea di cosa non funziona senza leggere il corpo del test. Il nome non è importante rispetto a quello.

    
risposta data 04.10.2011 - 09:51
fonte
1

Un modo per sapere se sei debole nei test è la tracciabilità. Di solito per i test, questo assume la forma di copertura.

L'obiettivo è misurare quali parti del codice vengono esercitate dai test, in modo da poter vedere il codice che non è coperto dai test. Spetta a te (e allo strumento di copertura) definire cos'è una "parte di codice". Il minimo è la copertura delle filiali.

    
risposta data 04.10.2011 - 10:20
fonte

Leggi altre domande sui tag