Estou usando um simples testador de unidade baseado em teste para testar meu aplicativo Django.
Meu próprio aplicativo está configurado para usar um logger básico em settings.py usando:
logging.basicConfig(level=logging.DEBUG)
E no meu código de aplicação usando:
logger = logging.getLogger(__name__)
logger.setLevel(getattr(settings, 'LOG_LEVEL', logging.DEBUG))
No entanto, ao executar unittests, eu gostaria de desativar o log para que não atrapalhe minha saída do resultado do teste. Existe uma maneira simples de desativar o log de maneira global, para que os criadores de log específicos do aplicativo não gravem coisas no console quando executo testes?
python
django
unit-testing
logging
shreddd
fonte
fonte
Respostas:
desativará todas as chamadas de log com níveis menos severos ou iguais a
CRITICAL
. O registro pode ser reativado comfonte
logging.disable
(a partir da resposta aceita) na parte superior dotests.py
aplicativo que está fazendo o registro.tearDown()
método:logging.disable(logging.NOTSET)
coloca o log de volta no lugar ordenadamente.tests
módulo é muito útil.Como você está no Django, você pode adicionar essas linhas às suas configurações.py:
Dessa forma, você não precisa adicionar essa linha em todos os
setUp()
seus testes.Você também pode fazer algumas alterações úteis para que suas necessidades de teste sejam feitas dessa maneira.
Há outra maneira "mais agradável" ou "mais limpa" de adicionar detalhes aos seus testes, e isso é criar seu próprio executor de testes.
Basta criar uma classe como esta:
E agora adicione ao seu arquivo settings.py:
Isso permite que você faça uma modificação realmente útil que a outra abordagem não faz, que é fazer o Django apenas testar os aplicativos que você deseja. Você pode fazer isso alterando a
test_labels
adição desta linha ao executor de teste:fonte
As outras respostas evitam "gravar coisas no console", configurando globalmente a infraestrutura de log para ignorar qualquer coisa. Isso funciona, mas acho uma abordagem muito franca. Minha abordagem é executar uma alteração na configuração, que faz apenas o necessário para impedir que os logs saiam no console. Então, adiciono um filtro de log personalizado ao meu
settings.py
:E eu configuro o log do Django para usar o filtro:
Resultado final: quando estou testando, nada vai para o console, mas todo o resto permanece o mesmo.
Por que fazer isso?
Projecto código que contém instruções de registro que são acionadas apenas em circunstâncias específicas e que devem gerar os dados exatos necessários para o diagnóstico, se algo der errado. Portanto, testo que eles fazem o que deveriam e, portanto, desativar completamente o log não é viável para mim. Não quero descobrir, depois que o software estiver em produção, que o que eu pensava que seria registrado não está registrado.
Além disso, alguns executores de teste (nariz, por exemplo) capturam logs durante o teste e emitem a parte relevante do log juntamente com uma falha no teste. É útil descobrir por que um teste falhou. Se o registro estiver completamente desativado, não há nada que possa ser capturado.
fonte
test_settings.py
arquivo que fica ao lado do meu projetosettings.py
. Ele é definido para carregarsettings.py
e fazer algumas mudanças, como conjuntoTESTING_MODE
paraTrue
. Meus executores de teste estão organizados de modo quetest_settings
seja o módulo carregado para as configurações do projeto Django. Há muitas maneiras de fazer isso. Eu costumo definir a variável de ambienteDJANGO_SETTINGS_MODULE
comoproj.test_settings
.Eu gosto da ideia do corredor de teste personalizado de Hassek. Note-se que
DjangoTestSuiteRunner
não é mais o executor de teste padrão no Django 1.6+, ele foi substituído peloDiscoverRunner
. Para o comportamento padrão, o executor de teste deve ser mais parecido com:fonte
helpers
, que possui apenas utilitários que não importam de qualquer outro lugar dentro do projeto.Descobri que, para testes em
unittest
uma estrutura ou similar, a maneira mais eficaz de desativar com segurança o log indesejado em testes de unidade é habilitar / desabilitar os métodossetUp
/tearDown
de um caso de teste específico. Isso permite que um destino seja especificamente onde os logs devem ser desativados. Você também pode fazer isso explicitamente no criador de logs da classe que está testando.fonte
Estou usando um decorador de método simples para desativar o log apenas em um método de teste específico.
E então eu o uso como no exemplo a seguir:
fonte
Existe algum método bonito e limpo para suspender o log de testes com o
unittest.mock.patch
métodofoo.py :
tests.py :
E
python3 -m unittest tests
não produzirá nenhuma saída de log.fonte
Às vezes você deseja os logs e às vezes não. Eu tenho esse código no meu
settings.py
Portanto, se você executar seu teste com as
--no-logs
opções, obterá apenas oscritical
logs:É muito útil se você deseja acelerar os testes no seu fluxo de integração contínua.
fonte
Se você não quiser ativá-lo / desativá-lo repetidamente em setUp () e tearDown () por unittest (não veja a razão disso), faça isso apenas uma vez por classe:
fonte
Nos casos em que desejo suprimir temporariamente um criador de logs específico, escrevi um pequeno gerenciador de contexto que achei útil:
Você então usa como:
Isso tem a vantagem de que o criador de logs seja reativado (ou retornado ao seu estado anterior) após a
with
conclusão.fonte
Você pode colocar isso no diretório de nível superior para o
__init__.py
arquivo de testes de unidade . Isso desativará o registro global no conjunto de testes de unidade.fonte
No meu caso, eu tenho um arquivo de configurações
settings/test.py
criado especificamente para fins de teste, eis como ele se parece:Eu coloquei uma variável de ambiente
DJANGO_SETTINGS_MODULE=settings.test
para/etc/environment
.fonte
Se você tiver diferentes módulos de inicialização para teste, desenvolvimento e produção, poderá desativar qualquer coisa ou redirecioná-lo no inicializador. Eu tenho local.py, test.py e production.py que todos herdam do common.y
O common.py faz toda a configuração principal, incluindo este trecho:
Então no test.py eu tenho o seguinte:
Isso substitui o manipulador de console por um FileHandler e ainda significa obter log, mas não preciso tocar na base de código de produção.
fonte
Se você estiver usando
pytest
:Como o pytest captura as mensagens de log e as exibe apenas para testes com falha, normalmente você não deseja desativar nenhum log. Em vez disso, use um
settings.py
arquivo separado para testes (por exemplo,test_settings.py
) e adicione-o:Isso diz ao Django para pular a configuração do log completamente. o
LOGGING
configuração será ignorada e pode ser removida das configurações.Com essa abordagem, você não obtém nenhum log para testes aprovados e todos os logs disponíveis para testes com falha.
Os testes serão executados usando o log que foi configurado por
pytest
. Pode ser configurado ao seu gosto naspytest
configurações (por exemplo,tox.ini
). Para incluir mensagens de log no nível de depuração, uselog_level = DEBUG
(ou o argumento da linha de comando correspondente).fonte