Quanto devono essere specifici i test unitari?

1

Non sono sicuro di cosa / se ci sia un gold standard su quanto un test unitario dovrebbe essere scomposto. Un'altra cosa è a volte mi chiedo se sto perdendo il mio tempo su un test specifico. Sono nuovo al test unitario / TDD. Ad esempio, ad esempio, ho un codice semplice come questo:

public class IntegerStats
{
    public int MaxValue { get; private set; }
    public int MinValue { get; private set; }
    public int NumberOfElements { get; private set; }
    public double AverageValue { get; private set; }

    public IntegerStats(int[] inputArray)
    {
        MaxValue = inputArray.Max();
        MinValue = inputArray.Min();
        AverageValue = inputArray.Average();
        NumberOfElements = inputArray.Length;
    }
}

I miei primi due test unitari assomigliano a questo:

[Test]
public void ProvideArrayReturnsIntStatsObject()
{

    int[] testArray = {1, 5, 254783, 98, 4793, 67};
    IntegerStats intStats = new IntegerStats(testArray);

    Assert.IsTrue(intStats.GetType().ToString().Contains("IntegerStats"));

}

[Test]
public void Length5ArrayLengthIs5()
{
    var result = new IntegerStats(new int[]{5,4,8,9,4});

    Assert.AreEqual(result.NumberOfElements,5);
}

Tuttavia, dovrei passare più array in questo test o dovrei eseguire diversi test sulla lunghezza di array di lunghezze diverse? Come faccio a sapere se il metodo è adeguatamente testato?

I miei prossimi progetti erano di continuare a testare le altre proprietà ... Ma poi mi stavo chiedendo se dovrei anche testare questi metodi dal momento che stanno usando algoritmi di libreria standard incorporati piuttosto che i miei algoritmi personalizzati in primo luogo .

Inoltre, avevo iniziato con un test per verificare se tutte le statistiche fossero accurate in un grande test, ma poi mi sono reso conto che non si trattava di un test unitario in quanto avrebbe potuto / dovrebbe essere suddiviso di più.

Qualunque consiglio / risorsa su questo sarebbe super utile. Il fatto è che ho letto molte cose su "Che test delle unità è", ma inserirmi nella pratica per me è stato molto diverso.

    
posta the_endian 22.10.2016 - 01:06
fonte

3 risposte

2

Non cercare di ottenere dai test unitari più di quanto puoi. Per assicurarti che una funzione sia corretta, dovresti testarla con tutti i possibili input (il più delle volte è molto costoso, se non impossibile). Pertanto, durante la scrittura di test, tieni presente che una funzione che supera i test non è corretta, ma piuttosto ha una minore probabilità di contenere errori.

La differenza tra alcuni test unitari per una funzione e una migliore è che il migliore si rivolge a luoghi in cui i bug possono / sono più comuni a verificarsi (questo è strettamente dal punto di vista di ciò che viene testato, ci sono altre qualità come la leggibilità). Di solito, mi piace vedere 3 cose in un test (questo è un po 'supponente):

  • Condizioni di errore: gli errori non sono davvero facili da vedere, a volte si verificano molto raramente nella pratica e potrebbero essere difficili da tracciare, quindi sarebbe bello testarli.

  • Uno o 2 ingressi (medi) comuni. Se i test falliscono, è facile vedere cosa succede in un caso di input comune e noioso, senza doversi preoccupare delle condizioni speciali.

  • Casi particolari: è qui che devi essere creativo. Ad esempio, stai elaborando un array. Cosa succede se l'array è vuoto? Dato che stai prendendo sia il minimo che il massimo della matrice, cosa succede se la matrice contiene solo un elemento?

Questo è solo il mio modo di pensare ai test, e sono sicuro che ci sono modi migliori là fuori. Ma il punto è avere qualcosa in mente quando si scrive un test. Non buttare semplicemente alcuni dati e dire "questo è un test", ma piuttosto riflettere attentamente su ciò che si desidera ottenere con quel test e se aggiungere valore alla propria suite di test.

    
risposta data 22.10.2016 - 03:17
fonte
3

In generale, purché abbia senso per te e se ritieni ragionevolmente sicuro che altri utenti che utilizzano il tuo codice e eseguiranno i tuoi test lungo la strada comprenderanno come sono scritti i tuoi test, allora dovresti essere in grado di scrivere test secondo ciò che sembra intuitivo. Se pensi che un metodo stia diventando troppo disordinato, suddividilo. Troppo complesso? Rompilo. Ci sono alcune discussioni su quante righe di codice devi limitare i tuoi metodi, ma la maggior parte dei programmatori avrà un'opinione diversa. Se è problematico per te o per qualcun altro della tua squadra, questo è un indicatore del tuo metodo troppo lungo o troppo corto.

Ho capito cosa stai dicendo se dovresti testare algoritmi integrati. Ecco come faccio ... Qualsiasi codice tu scrivi, dovresti testare, entro limiti ragionevoli. Vorrei anche considerare se il codice che scrivi ha bisogno di un test unitario. @MainMa ha dichiarato nei commenti seguenti:

TDD applies well to some code, and doesn't apply to other code. For instance, interfaces with the world won't be covered by unit tests; this is the goal of system tests. Also, there are situations where writing automated tests are simply prohibitively expensive.

Ovviamente tutto dipende dalle dimensioni del team, dal budget e dalla complessità della tua applicazione. Quindi devi sentirlo. In conclusione, alla fine della giornata si tratta di assicurarti che il codice che spedisci funzioni effettivamente, e che risolvi tutti i nodi prima che il tuo codice vada in produzione.

Ti consiglio di provare a scrivere i tuoi test in qualche modo generici, a meno che tu non stia testando qualcosa di specifico. Ad esempio, stai testando specificamente 5 elementi messi in una raccolta ... ma funziona con 6 elementi? 7? 8? Se non c'è nulla di specifico per il numero di elementi, prendi in considerazione la scrittura di un test che verifica in modo più generico il passaggio di array di lunghezze diverse. Nel tuo caso sopra, il secondo test è in realtà solo testando che un particolare campo sta diventando impostato correttamente, quindi vorrei prendere in considerazione la denominazione di quel test più appropriato al tuo campo NumberOfElements , come TestNumberOfElementsIsCorrect , quindi fai qualche controllo per vedere cosa succede quando vengono passati null , new []{} e new[]{...any number of items} .

Raccomando di mantenere i tuoi metodi piccoli. I metodi più piccoli sono più facili da eseguire il debug. Vorrei anche raccomandare che ogni singola asserzione all'interno di un particolare metodo di prova sia simile l'una all'altra. È quando inizi ad aggiungere più differenti asserzioni, che non sono ragionevolmente simili, che il tuo codice diventa difficile da leggere e difficile da gestire. Se hai un grosso metodo pieno di asserzioni che sono tutte simili, probabilmente è ok. Assicurati di commentare ciò che fai (commenta il metodo e qualsiasi codice dall'aspetto originale del metodo), e dovresti stare bene.

Spero che questo aiuti!

    
risposta data 22.10.2016 - 01:23
fonte
0

In Unit Testing (UT) e in particolare TDD, c'è un'enfasi sulla copertura del test, ma penso che la prima priorità (non esclusivamente) dovrebbe sfruttare le capacità di automazione di UT.

Pensa a come testare un particolare metodo senza scrivere un test. In qualche modo, passerai i parametri ed esaminerai l'output. È tutto manuale. Lo fai poche volte e se sei soddisfatto dei risultati, vai avanti. Lo svantaggio, se siamo onesti con noi stessi, scriverò più codice che fallirebbe questo test se lo facessi davvero. Non lo fai, quindi puoi leggere il codice e trovare il problema figlio.

Man mano che impari a creare UT, agisci in questo modo simile, ma scrivi test reali che imitano il modo in cui lo avresti testato prima di sapere che cos'è un UT. Non scrivere test per le cose che di solito non testare manualmente. "Se ho impostato questa proprietà pubblica su 2, sarà davvero 2?" Certo che lo farà. Mi rendo conto che questo non è TDD, ma Roma non è stata costruita in un giorno. Stai cercando di crescere come professionista della programmazione e non diventare una notte intera.

Mentre passi attraverso un particolare progetto o progetto, inizierai a trovare i problemi che potresti concludere evitando / rapidamente eseguendo il debug se un test lo avesse rilevato. Non solo dovresti creare quel test, ma iniziare a prendere in considerazione questi tipi di problemi nella tua futura codifica. Potresti non essere in grado di testarlo prima; ancora, stai ancora imparando, ma riconoscerai il beneficio immediato di avere questo tipo di test, quindi ti arriverà molto rapidamente.

Ecco come impari qualcosa e sviluppi la fluidità. Per molti programmatori, qualcosa come seguire uno standard di formattazione non richiede più tempo aggiuntivo nel loro codice perché quelle rientranze diventano un'abitudine.

Continuerete a migliorare come programmatori perché identificherete rapidamente se è necessario un test e come scriverlo. Questo è un enorme miglioramento della tua capacità di codificare (Come fanno quegli sviluppatori 10X farlo?) E se qualche sviluppatore junior domanda perché è necessario, avrai un sacco di storie sulle difficoltà che hai affrontato a questo modo nel modo più duro . Una volta convertiti, avrai sfruttato ancora di più i tuoi talenti. Chissà, potresti davvero imparare a non odiare TDD o pensare che sia uno spreco totale del tuo tempo.

Come nota a margine, penso che gli sviluppatori che non affrontano questo processo naturale, provano a saltare in cose come TDD prima che abbiano sviluppato le abilità dei prerequisiti e finiscano col cestinare molte metodologie come TDD, agile, Scrum, OOP, o qualsiasi altra cosa Mentre stiamo ancora cercando nel web una soluzione per far funzionare alcune funzionalità di base nel nostro programma, saremo davvero in grado di farlo tutto il tempo considerando la progettazione, l'architettura, gli standard, le prestazioni, i test e qualsiasi metodologia che stai cercando di aderire a tutti in una volta? Certo che puoi, ma non prima di aver imparato tutto il resto lungo la strada.

    
risposta data 22.10.2016 - 17:12
fonte

Leggi altre domande sui tag