C'è qualche ragione per usare i framework di testing invece di asserire per una leggera lib di funzioni pure?

1

Ho appena scritto una semplice libreria matematica che consiste in pure funzioni che prendono alcuni argomenti, eseguono alcuni calcoli e restituiscono un risultato. Mi piacerebbe scrivere test unitari per questa libreria, ma la maggior parte dei framework che potrei trovare (Jasmine, Mocha, QUnit, ecc.) Includono un'ampia gamma di bloat, che va dalla corrispondenza delle espressioni regolari alle chiamate asincrone. Non ho bisogno di fare nulla di ciò - anzi, un elenco di asserzioni funzionerebbe bene per me:

const assert = require("assert");
assert(functionA(a0, b0, c0) === d0)
assert(functionA(a1, b1, c1) === d1)
assert(functionA(a2, b2, c2) === d2)
assert(functionB(x0, y0) === z0)
assert(functionB(x1, y1) === z1)
...

Quali benefici ottengo dall'usare questi enormi framework piuttosto che una semplice lista di asserzioni?

    
posta MaiaVictor 16.10.2016 - 15:09
fonte

2 risposte

5

Il primo scopo di una suite di test è verificare che il codice funzioni come previsto.

Ma cosa succede se qualcosa va storto? Il secondo scopo è quello di rendere più facile per il programmatore capire facilmente cosa è andato storto e dove.

Diagnostica migliore

Quando una semplice asserzione fallisce, tutto ciò che viene detto è che non ha funzionato, nessun motivo per cui. Bene, almeno ci viene dato il numero di riga dell'asserzione fallita. Esempio di un quadro di prova immaginario:

ERROR: assertion failed
in test.js line 165:
assert(result === expected);

Questo rende complicato il debug del problema - dobbiamo guardare il codice sorgente per il test, registrare i valori prima dell'asserzione, rieseguire tutto, sperare che il problema sia ancora presente e quindi iniziare a cercare il bug.

Quando la funzione di asserzione non ha un valore booleano ma due valori da confrontare, può fornire messaggi di errore molto migliori:

ERROR: assertion failed
in test.js line 165:
assertEquals(result, expected);

got:      [42, 42, 42]
expected: [41, 42, 43]

Spesso, non dobbiamo nemmeno più esaminare il test e possiamo immediatamente capire il problema dai valori registrati.

Poiché l'uguaglianza non è l'unica relazione che potrebbe essere testata, ora abbiamo bisogno di varie funzioni assert* . Per esempio. assertNotEquals(result, otherValue) , assertThrows(function) , assertMatches(result, expectedRegex) , ....

Organizzazione di test migliore

Il prossimo vantaggio di un framework di test è che ci aiuta a organizzare i nostri test e semplifica l'elaborazione dei risultati del test.

Un singolo caso di test che verifica tutto è problematico, perché ciò rende difficile scoprire i test per un particolare modulo o funzione nel nostro codice sorgente. Preferisco una descrizione / organizzazione in stile RSpec:

describe("functionA", () => {
  it("sums the values", () => {
    assertEquals(functionA(2, 3, 4), 9);
  });

  it("throws for negative numbers", () => {
    assertThrows(() => functionA(2, 3, -1));
  });
});

Un messaggio di errore ora può spiegare chiaramente cosa stavamo testando:

test "functionA throws for negative numbers" failed:
did not throw
in test.js line 165:
    assertThrows(() => functionA(2, 3, -1));

Rapporti sui test migliori

Ancora più importante, il test runner è ora responsabile dell'esecuzione delle singole funzioni di test. Se un'affermazione fallisce, i test non correlati verranno comunque eseguiti. Ciò consente di sapere quanti test hanno fallito in totale, ad es. "FAILED 3 di 367 test" o "SUPERATO tutti i 367 test". Ciò ti aiuta a essere certo che tutti i tuoi test siano effettivamente eseguiti.

Alcuni test runner rendono più chiaro il loro output visualizzando solo i dettagli dei casi di test falliti e evidenziando parti importanti con i colori.

Inoltre, un corridore di test può scrivere i risultati del test in un formato leggibile dalla macchina, ad es. TAP o XML. Questi possono quindi essere visualizzati ed elaborati da IDE o strumenti di integrazione continua.

    
risposta data 16.10.2016 - 17:36
fonte
0

Se esegui test unitari in modo corretto, l'enorme vantaggio che otterrai sarà quello di rimuovere i test dalla tua libreria. Non devi verificare che functionA funzioni ogni volta che esegui functionA . Devi testarlo ogni volta che lo riscrivi.

I test di convalida dell'input dovranno ancora essere eseguiti in fase di esecuzione, ma controllare che i metodi forniscano il risultato corretto non è necessario che vengano eseguiti con tali metodi. Quel codice può essere spostato altrove. Quindi i tuoi utenti non vedranno mai o eseguiranno questo codice di test. Fai questo e nient'altro che il tuo ambiente di sviluppo sa anche quale framework stai usando.

Alcuni framework ti inviteranno a diventare dipendenti da loro perché ciò è positivo per la loro attività. Non tanto per il tuo. Sentiti libero di trattarli come una biblioteca. Utilizza solo ciò di cui hai bisogno solo dove ti serve.

    
risposta data 16.10.2016 - 17:29
fonte

Leggi altre domande sui tag