2009-06-03 10 views
6

Ho trovato una soluzione, vedere la mia risposta qui sotto. Qualcuno ha uno più elegante?Posso eseguire automaticamente i test JUnit una volta con tutte le registrazioni abilitate e una volta con tutte le registrazioni disabilitate?

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

Assumere il seguente classe da testare:

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 prova di classe:

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

Uno strumento in codice di copertura come ad esempio Cobertura riferirà correttamente che solo alcuni dei rami condizionali sono stati controllati.

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

Oltre ad avere un aspetto negativo nel punteggio di copertura, questo rappresenta un rischio reale.

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

Quindi la mia conclusione è che il codice che contiene le dichiarazioni logger dovrebbe sempre essere provato una volta con tutta la registrazione attivata e una volta con tutta la registrazione disabilitata ...

Is c'è un modo per fare qualcosa del genere con JUnit? So come abilitare o disabilitare globalmente tutte le mie registrazioni 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. Sono a conoscenza di this question 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 possono essere contenuti in un if (logger.isDebugEnabled()).

risposta

4

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

L'articolo Writing a parameterized JUnit test conteneva la soluzione.

Vedere LoggingTestBase per la classe di base di registrazione e LoggingTestBaseExampleTest per un semplice esempio che lo utilizza.

Ogni metodo di prova contenuta viene eseguito tre volte:

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

2. Viene eseguito con tutte le registrazioni abilitate e scritte in un file. Questo file viene eliminato dopo il test.

3. Viene eseguito con tutte le registrazioni disabilitate.

Sì, LoggingTestBase ha bisogno di documentazione;)

+0

Nota: non è consigliabile gestire i livelli di registro per un'applicazione tipica scrivendo la configurazione dall'applicazione. I framework di registrazione sono progettati per gestire questo esterno all'applicazione. –

+0

Sono test unitari, non è un'applicazione. Inoltre, ci sono certamente casi in cui la configurazione a livello di loog cambiava, ad es. un'opzione di riga di comando '-v' di un'applicazione di console. – Huxi

+0

È possibile configurare logback programmaticamente senza Joran. Avresti un codice più breve. Inoltre, se la configurazione fosse stata programmata, è possibile ripristinare la vecchia configurazione alla fine di ogni test. Holler su logback-dev se desideri vedere un codice di esempio. Altrimenti, lavoro molto bello! – Ceki

2

Si consiglia di passare da JUnit a TestNG. TestNG ha molte funzionalità avanzate su JUnit. Ti consente di eseguire i test più volte con una configurazione diversa e credo sia quello che ti serve

+0

È possibile combinare JUnit e TestNG? Sto parlando più o meno dell'integrazione di Maven 2 qui ... tutti i nostri test sono test JUnit ... – Huxi

+0

Sì, TestNG può eseguire test JUnit. Lo uso sempre nei progetti maven2 – artemb

+0

La conversione di un test da TestNG a JUnit è semplice, anche se richiede un consumo di tempo – artemb

3

Hai provato semplicemente il mantenimento di due file di configurazione di registro separati? Ognuno dovrebbe accedere a diversi livelli dal root logger.

Tutti accedendo disabilitato:

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

Tutti attivata la registrazione:

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

esecuzione sarebbe specificare configurazioni differenti sul percorso di classe tramite un parametro di sistema:

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

Stavo pensando più alle linee di Maven 2 e Logback. Avere due configurazioni e inizializzare il framework di registrazione non è un problema. L'esecuzione dei test due volte chiamando il rispettivo metodo di configurazione del logger è il mio problema. Avrei dovuto dirlo più chiaramente, penso. – Huxi

+1

è possibile specificare i parametri di sistema in un profilo choosable. Vuoi due profili, uno con registrazione e uno senza. Il fatto che entrambi eseguano con un comando è al di là del mio ken – Jherico

+0

@Huxi: nota, il file di configurazione del log non serve solo per inizializzare il framework di registrazione, ma anche per controllare i livelli di log (che è ciò che stai cercando di fare). Eseguendo due (o tre) esecuzioni di test, stai realizzando ciò che desideri senza costringere gli sviluppatori a creare 3 test unitari per questa funzionalità (che è ciò che stai proponendo). È possibile controllare quale configurazione di registro viene scelta da ciascuna esecuzione utilizzando diversi profili maven. Uno script può occuparsi dell'esecuzione delle esecuzioni in un unico comando. –

1

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

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

Per 3.8 inserire tutto in suite e creare due suite, una per ogni livello di registrazione, che imposta il livello di registrazione prima dell'esecuzione dei test. Questo è funzionalmente la stessa cosa che eseguire l'intera suite di test due volte con parametri della riga di comando diversi, tranne che si ottiene con una corsa.

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

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

L'altro è test parametrizzati. Anche se in realtà dovresti impostare ogni test per prendere i parametri (questo richiede un costruttore che accetta gli argomenti) e quindi impostare il livello di log in base al parametro.

MODIFICA: in risposta alla richiesta di un how-to sui test parametrici, here è la javadoc sul runner per iniziare, e here è una guida più pratica.

+0

Hai qualche link a docu sui test parametrizzati? Le FAQ di JUnit sono state aggiornate l'ultima volta nel 2006 e non sono riuscito a trovare nulla di simile ... Cosa succede su junit.org ?? Anche il libro di cucina sembra obsoleto ... – Huxi

+0

Grazie per il suggerimento "test parametrizzati". Ho trovato della documentazione, vedi la mia soluzione. – Huxi

0

Se ritieni di avere troppa registrazione se si accende tutto, forse si potrebbe provare a ridurre la quantità di registrazione. Non è molto utile se è troppo per il computer non elaborare un essere umano da leggere.

+0

Instrado tutto il log in un file temporaneo in modo che l'output non sia ingombra di messaggi di registrazione inutili. Il punto centrale della mia domanda è che mi piacerebbe essere in grado di testare entrambi gli scenari: tutta la registrazione attivata e tutta la registrazione disattivata. Abbiamo davvero avuto la situazione che una classe avrebbe funzionato se eseguita con debug abilitato e non con le sole informazioni abilitate. Mi piacerebbe cogliere questi problemi in modo generale. – Huxi

Problemi correlati