Come testare un caso mancante in un'istruzione switch in cui tutti i casi sono veri

4

Uso spesso enum tipi nel mio codice con un passaggio per applicare la logica a ciascun tipo. In questi casi è importante che ogni enum abbia implementato il codice.

Ad esempio;

public enum eERROR
{
    REQUIRED,
    DUPLICATE,
    UNKNOWN,
    MISSING_VALUE
}

public void Error(eERROR pError)
{
    switch (pError)
    {
        case eERROR.REQUIRED:
            // ......
            return;
        case eERROR.DUPLICATE:
            // ......
            return;
        case eERROR.MISSING_VALUE:
            // ......
            return;
        case eERROR.UNKNOWN:
            // ......
            return;
    }

    throw new InvalidArgumentException("Unsupported error type");
}

In fondo ho aggiunto un'eccezione come ultima risorsa per verificare che un programmatore si sia ricordato di aggiungere nuovi tipi di enum all'istruzione switch . Se un nuovo tipo viene aggiunto a eERROR , l'eccezione potrebbe essere generata se il codice non viene aggiornato.

Ecco il mio problema.

Il codice sopra riportato genera una copertura del test unitario di solo 99% perché non posso attivare l'eccezione. Potrei aggiungere un generico unhandled a eERROR e chiamare Error(eERROR.unhandled) solo per ottenere una copertura 100% , ma mi sembra un trucco per risolvere qualcosa che non è un problema solo per ottenere una copertura completa . Potrei rimuovere la linea ma poi non ho il controllo di sicurezza.

Perché il 99% è un problema? perché la base di codice è così grande che qualsiasi metodo scoperto non sposta la copertura a 98% . Quindi vedo sempre 99% e non so se ho perso un metodo o due.

Come posso riscrivere Error() in modo che tutte le enumerazioni aggiunte di recente che non vengono aggiunte allo switch vengano catturate in qualche modo dal programmatore e siano anche coperte dai test. C'è un modo per farlo senza aggiungere un dummy enum?

    
posta cgTag 29.01.2014 - 16:56
fonte

5 risposte

4

A seconda della lingua, dovresti essere in grado di passare un valore spazzatura al costruttore Error. La maggior parte delle lingue usa solo numeri interi per i valori enum. In pseudo-codice:

e = new Error(eError -1)
>> InvalidArgumentException: Unsupported error type
    
risposta data 29.01.2014 - 17:57
fonte
6

Come sviluppatore che applica lo sviluppo basato sui test da un giorno all'altro, credo che la domanda dovrebbe essere il contrario. Quando non riesci a testare il codice non c'è motivo per quel codice. Puoi estendere l'enum per ereditarietà (se possibile) o usare una simulazione per attivare un caso specifico.

    
risposta data 29.01.2014 - 20:19
fonte
1

non puoi codice di test che deve essere eseguito solo in caso di errore di programmazione, perché ciò implicherebbe che la tua suite di test possa funzionare correttamente solo se c'è un errore di programmazione nel codice base! Il fatto che sia comunque utile scrivere tali guardie contro casi apparentemente impossibili è uno dei motivi per cui l'obiettivo "copertura del codice assolutamente al 100%" non è un buon obiettivo.

    
risposta data 29.01.2014 - 17:06
fonte
1

Una domanda hai bisogno della clausola catch all affatto? Se un nuovo elemento viene aggiunto all'Enum, il correttore di tipi lo prenderà per te? So che in Erlang se hai scritto qualcosa come la dichiarazione del caso, dialyzer ti avrebbe detto chiaramente che non c'è modo che il caso di errore possa mai combaciare con l'analisi statica.

Forse sono solo viziato da ottimi strumenti che non esistono in tutte le lingue.

    
risposta data 29.01.2014 - 19:32
fonte
0

Che ne pensi di questo, puoi testare con null come valore non valido?

public void Error(eERROR pError)
{
    if (pError != null) {
        switch (pError)
        {
            // ......
        }
    }

    throw new InvalidArgumentException("Unsupported error type: " + pError);
}
    
risposta data 29.01.2014 - 18:57
fonte

Leggi altre domande sui tag