Scrittura di test per due metodi che condividono funzionalità

0

Sto scrivendo alcuni test per un modulo NodeJS, ma questa domanda può essere applicata per qualsiasi lingua / piattaforma. Ho la seguente situazione:

// in moduleA.js

exports.foo = function (var1, var2) {
    // do something to var1 and var2 here

    baz(var1, var2);
};

exports.bar = function (var1, var2) {
    // do something completely different to var1 and var2 here

    baz(var1, var2);
};

function baz(var1, var2) {
    // do something to var1 and var2 yet again that both foo and bar need

    moduleB.doSomething(var1, var2);
}

Quindi, sia foo che bar sono metodi pubblici di moduleA . Hanno alcune funzionalità specifiche (fanno cose diverse a var1 e var2 ) ma anche alcune funzionalità condivise (per mantenere le cose asciutte l'ho spostato in un metodo privato, baz ) e poi chiamano entrambe un metodo pubblico su moduleB .

Ho cancellato moduleB quindi so esattamente cosa sta succedendo dopo aver chiamato foo e bar . Sto scrivendo i test per foo e% per la funzionalità specifica di% di gen_de ma non sono sicuro al 100% come affrontare la verifica della funzionalità condivisa in bar .

Mi sembra di avere tre opzioni:

  • scrivi test identici sia per baz che foo che testano le cose in bar
  • scrivi un singolo test per baz e non scrivi lo stesso test per foo poiché sai che bar funziona
  • espone baz come un altro metodo pubblico per il modulo e testalo separatamente.

Mi sto appoggiando alla prima opzione, ma sento che potrei mancare qualcosa.

    
posta Andrey 06.03.2014 - 12:34
fonte

3 risposte

3

I test unitari non dovrebbero interessarsi ai dettagli di implementazione. I test unitari devono verificare che la funzione restituisca il risultato atteso, causi gli effetti collaterali attesi (e, se possibile, non causando altri effetti collaterali) e lanci le eccezioni previste. In che modo le funzioni non dovrebbero riguardare i test di unità, proprio come non dovrebbero riguardare l'utente del modulo.

Non è necessario eseguire il test dell'unità baz (a meno che non si tratti di un test dell'unità interna del modulo) perché non fa parte dell'API del modulo. Ciò significa che dovresti essere in grado di rimuoverlo, rinominarlo o modificarne la funzionalità fintanto che le funzioni pubbliche del modulo continuano a funzionare, e né il codice utente che utilizza il modulo né i test delle unità dovrebbero cambiare.

Con questo approccio, è facile vedere che dovresti scegliere la prima opzione: scrivi test unitari sia per foo che bar . I test unitari non dovrebbero preoccuparsi di baz , poiché dovresti essere in grado di rifattorizzarlo con foo e / o bar , o per crearne una nuova versione - baz2 - quale bar sarà utilizza mentre foo continua a utilizzare baz originale o modifica un percorso di esecuzione di baz che né foobar dovrebbero mai richiamare. Quelle probabilità non influiscono sull'utente del modulo, quindi non dovrebbero influenzare neanche il test dell'unità.

Se baz ha alcuni effetti collaterali che foo attiva, l'utente del modulo e l'unità test si preoccupano di quelli sono effetti collaterali di foo , quindi dovresti testarli di conseguenza.

    
risposta data 06.03.2014 - 12:56
fonte
6

La chiave è pensare in test per funzionalità / comportamento non in test per i metodi.

È difficile senza nomi veri, ma "foo" esiste per offrire un comportamento, lo stesso con "bar", hai semplicemente bisogno di test per verificare che il comportamento di foo sia corretto e altro per verificare il comportamento di "bar" , quando scopri che questi due metodi condividono alcune funzionalità interne e decidi di fare un refactoring il tuo test rimane lo stesso, e grazie a ciò puoi essere sicuro che il tuo refactoring non rotti alcuna funzionalità.

So che è probabilmente un consiglio generico, ma è davvero difficile senza un esempio concreto.

    
risposta data 06.03.2014 - 12:56
fonte
0

Il test per moduleB.doSomething() non appartiene a questo test, eccetto incidentalmente. Dovrebbe essere nel test per il modulo B.

Se baz era privato per il suo modulo, e qualunque cosa faccia è parte del contratto pubblico per diverse routine che lo usano, allora i suoi effetti dovrebbero essere testati. Così com'è, il massimo che dovresti fare è interrogare il tuo B mock object se baz è stato chiamato , non se ha fatto il suo lavoro.

    
risposta data 06.03.2014 - 12:42
fonte

Leggi altre domande sui tag