devo testare questo metodo pubblico

3

Ho la seguente semplice implementazione:

var VALIDATION_TYPES = {
    ERROR: 1,
    WARNING: 2
};
var validationRules = {};

this.addErrorRule = function (event, rule) {
    addValidationRule(event, VALIDATION_TYPES.ERROR, rule);
};

var addValidationRule = function (event, type, rule) {
    if (!validationRules[event]) {
        validationRules[event] = {};
        validationRules[event][VALIDATION_TYPES.ERROR] = [];
        validationRules[event][VALIDATION_TYPES.WARNING] = [];
    }

    validationRules[event][type].push(rule);
};

Mi chiedo se addErrorRule debba essere testato unitamente e se sì, come? Devo esporre validationRules oggetto a unit test?

EDIT:

Potrei modificare il mio addValidationRule per restituire il numero di regole aggiunte e controllare quel numero nel mio test:

var addValidationRule = function (event, type, rule) {
    var countAddedRules = 0;

    if (!validationRules[event]) {
        validationRules[event] = {};
        validationRules[event][VALIDATION_TYPES.ERROR] = [];
        validationRules[event][VALIDATION_TYPES.WARNING] = [];
    }

    var originalCount = validationRules[event][type].length;
    validationRules[event][type].push(rule);
    countAddedRules = originalAddedRulesCount - validationRules[event][type].length;
    return countAddedRules;
};
    
posta Max Koretskyi aka Wizard 19.01.2015 - 17:13
fonte

2 risposte

3

Penso che entrambi i metodi di test proposti finora siano pessimi.

omouse suggerisce di esporre validationRules a un dettaglio di implementazione interna. In tal modo, suggerisce di testare l'implementazione quando si deve testare l'interfaccia. Vedi questo blog per la discussione .

L'op ha quindi proposto di restituire il numero di regole aggiunte. Ma per quanto posso dire, ritornerà sempre 1. Anche se il metodo restituisse valori variabili, testeresti solo i valori restituiti, non la funzionalità effettiva a cui sei interessato.

Quindi, come testate questo metodo? Innanzitutto, non pensarci in termini di come testare quel metodo. Invece, pensa a quale comportamento vuoi testare. Non pensare allo stato interno, o come lo fa. Pensa a come il metodo verrà utilizzato nel resto del tuo programma.

Presumibilmente, vuoi essere in grado di fare qualcosa del genere:

validator.addErrorRule('foobar', function(payload) {
   if (payload.cost > 50) {
        return "No. Price Too High";
   }
});
validation_results = validator.validate(payload)

Tutto ciò di cui abbiamo bisogno per trasformarlo in un test è:

assert.deepEqual(validation_results, [
    {validator: 'foobar', error: 'No. Price Too High'}
])

Questo in realtà mette alla prova la funzionalità che ci interessa ed evita di introdurre dettagli di implementazione.

Molti programmatori hanno avuto l'idea di dover testare ogni metodo in modo indipendente. Ecco perché le persone pensano di dover testare addErrorRule separatamente da validate . Non cadere in questa trappola. I metodi all'interno dello stesso oggetto sono in genere strettamente interconnessi e il tentativo di testarli in modo indipendente è un compito da scemo. Inoltre, perdi la possibilità di testare l'interazione tra i metodi che di solito è l'intero punto della funzionalità che desideri.

    
risposta data 19.01.2015 - 18:39
fonte
2

Sicuramente dovresti essere unit-testing addErrorRule . Puoi farlo testando gli effetti collaterali della chiamata addValidationRule . Assicurati che vi sia una regola di convalida aggiunta all'elenco di destra (errori, non avvisi).

Sì, devi esporre la variabile validationRules per poter testare unitamente addErrorRules .

Ecco il codice di esempio su come potrebbe apparire il test unitario:

assertEquals(validationRules.length, 0);

addErrorRule('an error event', 'this is the rule');
assertEquals(validationRules['an error event'][VALIDATION_TYPES.WARNING].length, 0);
assertEquals(validationRules['an error event'][VALIDATION_TYPES.ERROR].length, 1);
assertEquals(validationRules['an error event'][VALIDATION_TYPES.ERROR][0], 'this is the rule');

Non devi andare oltre perché allora stai solo testando gli effetti collaterali generali della funzione addValidationRule (che dici che stai già facendo).

Non usare Mock o Mock Objects per questo!

È possibile usare i mock per questo, ma poi devi mettere in discussione ciò che stai provando veramente qui: fa aggiungereErrorRule gli effetti collaterali corretti, o è sufficiente che chiami il metodo addValidationRule e possiamo tranquillamente presumere che gli effetti collaterali saranno corretti?

Se è quest'ultimo, se stai testando con un metodo di simulazione, non puoi controllare il risultato corretto in validationRules perché sarà riempito con qualsiasi valore di ritorno che fornisci nella simulazione che sconfigge lo scopo di testare addErrorRule interamente.

L'unica volta che useresti un mock per questo caso sarebbe se usassi una libreria o un'API che sono difficili da testare o che richiede molto tempo per testare (ad esempio, vorrai prendere in giro le chiamate al database o al filesystem o chiamate all'API REST remote e si presuppone che forniscano gli effetti collaterali corretti).

    
risposta data 19.01.2015 - 17:27
fonte

Leggi altre domande sui tag