Posso automaticamente executar casos de teste JUnit uma vez com todo o log ativado e uma vez com todos os logs desativada?

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

Pergunta

Eu encontrei uma solução, ver a minha própria resposta abaixo. Alguém tem um mais elegante?

Eu quero fazer isso para aumentar de cobertura de código e encontrar erros sutis.

Suponha que a seguinte classe a ser testado:

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 a seguinte classe de teste:

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

A ferramenta de cobertura de código, como por exemplo Cobertura irá relatar corretamente que somente alguns dos ramos condicionais foram verificados.

informações e depuração ou são ativados ou desativados para o logger.

Além de olhar ruim em sua pontuação de cobertura, isso representa um risco real.

E se há algum efeito colateral causado por dentro do código if (logger.isDebugEnabled ())? E se o seu código faz só funcionam se depuração está habilitado e falha miseravelmente se o nível de log é definido como INFO? (Isso realmente aconteceu em um de nossos projetos: p)

Assim, a minha conclusão é que o código que contém instruções logger deve sempre ser testado uma vez com todo o log ativado e uma vez com todos os logs desativada ...

Existe uma maneira de fazer algo parecido com JUnit? Eu sei como ativar globalmente ou desativar todo o meu registo no Logback então o problema é: Como posso executar os testes duas vezes, uma vez com o registo activado, uma vez com o log desativado

.

P.S. Estou ciente esta questão mas eu não acho que este é um duplicado. Estou menos preocupado com os valores de cobertura absolutos, mas sobre erros sutis, difíceis de encontrar que possam estar contidos dentro de um if (logger.isDebugEnabled ()).

Foi útil?

Solução

Eu já resolveu este problema através da implementação de uma classe base que classes de teste deve se estender, se tal funcionalidade é desejada.

O artigo Escrevendo um teste JUnit parametrizado continha a solução.

Veja LoggingTestBase para a classe base madeireira e LoggingTestBaseExampleTest para um exemplo simples que está a usá-lo.

Cada contido método de teste é executado três vezes:

1. É executado usando o registro conforme definido no logback-test.xml como de costume. Isto é suposto para ajuda ao escrever / depurar os testes.

2. É executado com todo o log ativado e gravados em um arquivo. Este arquivo é excluído após o teste.

3. É executado com todo o log desativado.

Sim, LoggingTestBase precisa de documentação;)

Outras dicas

Você já tentou simplesmente manter dois arquivos de configuração log separados? Cada um teria log em diferentes níveis do logger raiz.

Todo o log desativado :

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

Todos os log habilitado :

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

A execução deve especificar diferentes configurações no classpath via um parâmetro do sistema:

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

Eu recomendaria comutação de JUnit para TestNG. TestNG tem um monte de recursos avançados mais de JUnit. Ele permite que você executar os testes várias vezes com configuração diferente e eu acho que é o que você precisa

eqbridges sugestão de simplesmente executar os testes duas vezes com diferentes contextos madeireiras parece o mais simples. Você não tem que se lembrar de código a lógica em todos os testes abençoada, para uma grande vantagem. A outra é que você pode ver que nível de registo é a culpa com muita facilidade.

Dito isto, há um par de estratégias se você só tinha de fazer isso em uma corrida de teste.

Para 3,8 Gostaria de colocar tudo em suites, e fazer duas suites, um para cada nível de log, que define o nível de log antes de executar os testes. Esta é funcionalmente a mesma coisa que executar toda a suíte de testes duas vezes com diferentes parâmetros de linha de comando, exceto que você começa com uma corrida.

Na JUnit 4.x um par de opções adicionais vêm à mente:

Um é um corredor de costume. Embora eu não posso pensar fora da mão de tudo o que você teria que fazer para fazer este trabalho, mas um corredor que realmente executa o teste duas vezes e anotar o teste com @RunWith seu corredor costume poderia funcionar.

O outro é testes com parâmetros. Embora você realmente tem que configurar todos os testes para tirar parâmetros (isto requer um construtor que leva os argumentos) e, em seguida, definir o nível de log de acordo com o parâmetro.

EDIT: Em resposta ao seu pedido para um como-nos testes paramterized, aqui é o javadoc no corredor para você começar, e aqui é um guia mais prático.

Se você sente que tem muito de registro se você transformar tudo em, talvez você poderia tentar reduzir a quantidade de registro. A sua não é muito útil se demasiado para o computador para procude nunca mente um ser humano para ler.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top