Posso eseguire automaticamente i test JUnit una volta con tutte le registrazioni abilitate e una volta con tutte le registrazioni disabilitate?

StackOverflow https://stackoverflow.com/questions/945659

Domanda

Ho trovato una soluzione, vedi la mia risposta qui sotto.Qualcuno ne ha uno più elegante?

Voglio farlo per aumentare la copertura del codice e trovare bug sottili.

Supponiamo che venga testata la seguente classe:

public class Foo {
    private final Logger logger = LoggerFactory.getLogger(Foo.class);
    public void bar() {
        String param=[..];
        if(logger.isInfoEnabled()) logger.info("A message with parameter {}", param);

        if(logger.isDebugEnabled()) {
            // some complicated preparation for the debug message
            logger.debug([the debug message]);
        }
    }
}

e la seguente classe di test:

public class FooTest {
    @Test
    public void bar() {
        Foo foo=new Foo();
        foo.bar();
    }
}

Uno strumento di copertura del codice come ad es.Cobertura riporterà correttamente che solo alcuni dei rami condizionali sono stati controllati.

info e debug sono attivati ​​o disattivati ​​per il logger.

Oltre a sembrare pessimo nel tuo punteggio di copertura, questo rappresenta un rischio reale.

Cosa succede se c'è qualche effetto collaterale causato dal codice all'interno di if(logger.isDebugEnabled())?Cosa succede se il tuo codice funziona solo se DEBUG è abilitato e fallisce miseramente se il livello di registro è impostato su INFO?(Questo è realmente accaduto in uno dei nostri progetti :p)

Quindi la mia conclusione è che il codice contenente le istruzioni del logger dovrebbe sempre essere testato una volta con tutte le registrazioni abilitate e una volta con tutte le registrazioni disabilitate...

C'è un modo per fare qualcosa del genere con JUnit?So come abilitare o disabilitare globalmente tutti i miei accessi in Logback, quindi il problema è:Come posso eseguire i test due volte, una volta con la registrazione abilitata, una volta con la registrazione disabilitata.

p.s.ne sono consapevole questa domanda ma non penso che questo sia un duplicato.Sono meno preoccupato per i valori di copertura assoluti ma per i bug sottili e difficili da trovare che potrebbero essere contenuti all'interno di un if(logger.isDebugEnabled()).

È stato utile?

Soluzione

Ho risolto questo problema implementando una classe base che le classi di test dovrebbero estendere se si desidera tale funzionalità.

L'articolo Scrittura di un test JUnit parametrizzato conteneva la soluzione.

Vedere LoggingTestBase per la classe base di registrazione e LoggingTestBaseExampleTest per un semplice esempio di utilizzo.

Ogni metodo di test contenuto viene eseguito tre volte:

1. Viene eseguito utilizzando la registrazione come definito in logback-test.xml come al solito.Questo dovrebbe aiutare durante la scrittura/il debug dei test.

2. Viene eseguito con tutta la registrazione abilitata e scritta in un file.Questo file viene eliminato dopo il test.

3. Viene eseguito con tutta la registrazione disabilitata.

Sì, LoggingTestBase necessita di documentazione ;)

Altri suggerimenti

Hai provato semplicemente a mantenere due file di configurazione del registro separati?Ognuno registrerebbe a livelli diversi dal root logger.

Tutta la registrazione disabilitata:

...
<root>
    <priority value="OFF"/>
    <appender-ref ref="LOCAL_CONSOLE"/>
</root>
...

Tutte le registrazioni sono abilitate:

...
<root>
    <priority value="ALL"/>
    <appender-ref ref="LOCAL_CONSOLE"/>
</root>
...

L'esecuzione specificherebbe diverse configurazioni sul classpath tramite un parametro di sistema:

-Dlog4j.configuration=path/to/logging-off.xml
-Dlog4j.configuration=path/to/logging-on.xml

Consiglierei di passare da JUnit a TestNG.TestNG ha molte funzionalità avanzate rispetto a JUnit.Ti consente di eseguire i test più volte con configurazioni diverse e immagino sia ciò di cui hai bisogno

Il suggerimento di eqbridge di eseguire semplicemente i test due volte con contesti di registrazione diversi sembra il più semplice.Non devi ricordarti di codificare la logica in ogni benedetto test, con un grande vantaggio.L'altro è che puoi vedere molto facilmente quale livello di registrazione è da incolpare.

Detto questo, ci sono un paio di strategie se dovessi farlo in un solo giro di prova.

Per la versione 3.8 metterei tutto in suite e creerei due suite, una per ciascun livello di registrazione, che imposta il livello di registrazione prima di eseguire i test.Funzionalmente è la stessa cosa che eseguire l'intera suite di test due volte con parametri della riga di comando diversi, tranne per il fatto che lo ottieni con una sola esecuzione.

In JUnit 4.x mi vengono in mente un paio di opzioni aggiuntive:

Uno è un corridore personalizzato.Anche se non riesco a pensare a tutto ciò che dovresti fare per farlo funzionare, ma un corridore che esegue effettivamente il test due volte e annota il test con @RunWith il tuo corridore personalizzato potrebbe funzionare.

L'altro sono i test parametrizzati.Sebbene in realtà dovresti impostare ogni test per accettare parametri (questo richiede un costruttore che accetta gli argomenti) e quindi impostare il livello di registro in base al parametro.

MODIFICARE:In risposta alla tua richiesta di how-to sui test parametrizzati, Qui è il Javadoc sul runner per iniziare e Qui è una guida più pratica.

Se ritieni di avere troppe registrazioni se accendi tutto, forse potresti provare a ridurre la quantità di registrazioni.Non è molto utile se è troppo per il computer procurare e non importa a un essere umano da leggere.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top