Como se escreve um unittest que falha apenas se uma função não lança uma exceção esperada?
python
unit-testing
exception
exception-handling
Daryl Spitzer
fonte
fonte
myfunc
você deve adicioná-los como argumentos à chamada assertRaises. Veja a resposta de Daryl Spitzer.self.assertRaises(TypeError, mymod.myfunc)
. Você pode encontrar uma lista completa das exceções integradasself.assertRaises(SomeCoolException, Constructor, arg1)
Desde o Python 2.7, você pode usar o gerenciador de contexto para obter o objeto Exception real lançado:
http://docs.python.org/dev/library/unittest.html#unittest.TestCase.assertRaises
Em Python 3.5 , você tem que envolver
context.exception
emstr
, caso contrário, você vai ter umTypeError
fonte
context.exception
não transmite a mensagem; é um tipo.import unittest2
, você precisa usarstr()
, ieself.assertTrue('This is broken' in str(context.exception))
.O código na minha resposta anterior pode ser simplificado para:
E se a função funcionar com argumentos, basta passá-los para assertRaises como este:
fonte
2.7.15
. Seafunction
inself.assertRaises(ExpectedException, afunction, arg1, arg2)
é o inicializador de classe, você precisa passarself
como o primeiro argumento, por exemplo:self.assertRaises(ExpectedException, Class, self, arg1, arg2)
Resposta curta:
Use o
self.assertRaises
método como um gerenciador de contexto:Demonstração
A abordagem de melhores práticas é bastante fácil de demonstrar em um shell Python.
A
unittest
bibliotecaNo Python 2.7 ou 3:
No Python 2.6, você pode instalar um backport da
unittest
biblioteca do 2.7 , chamado unittest2 , e apenas o pseudônimo deunittest
:Testes de exemplo
Agora, cole no seu shell Python o seguinte teste de segurança de tipo do Python:
Teste um usa
assertRaises
como gerenciador de contexto, o que garante que o erro seja capturado e limpo adequadamente, enquanto registrado.Também podemos escrevê-lo sem o gerenciador de contexto, veja o teste dois. O primeiro argumento seria o tipo de erro que você espera gerar, o segundo argumento, a função que você está testando e os argumentos e palavras-chave restantes serão passados para essa função.
Eu acho que é muito mais simples, legível e sustentável apenas para usar o gerenciador de contexto.
Executando os testes
Para executar os testes:
No Python 2.6, você provavelmente precisará do seguinte :
E seu terminal deve gerar o seguinte:
E vemos que, como esperamos, tentando adicionar um
1
e um'1'
resultado em umTypeError
.Para uma saída mais detalhada, tente o seguinte:
fonte
Seu código deve seguir este padrão (este é um teste de estilo de módulo mais unittest):
No Python <2.7, essa construção é útil para verificar valores específicos na exceção esperada. A função mais unittest
assertRaises
verifica apenas se uma exceção foi levantada.fonte
assertRaises
, obterá um ERRO ao invés de uma FALHA.from: http://www.lengrand.fr/2011/12/pythonunittest-assertraises-raises-error/
Primeiro, aqui está a função correspondente (ainda dum: p) no arquivo dum_function.py:
Aqui está o teste a ser executado (apenas este teste é inserido):
Agora estamos prontos para testar nossa função! Aqui está o que acontece ao tentar executar o teste:
O TypeError é ativado no momento e gera uma falha no teste. O problema é que esse é exatamente o comportamento que queríamos: s.
Para evitar esse erro, basta executar a função usando lambda na chamada de teste:
A saída final:
Perfeito!
... e para mim também é perfeito !!
Muito obrigado Sr. Julien Lengrand-Lambert
Esta afirmação de teste realmente retorna um falso positivo . Isso acontece porque o lambda dentro de 'assertRaises' é a unidade que gera erro de tipo e não a função testada.
fonte
self.assertRaises(TypeError, df.square_value(self.false_int))
chama o método e retorna o resultado. O que você quer é passar o método e quaisquer argumentos e deixar o unittest para chamá-lo:self.assertRaises(TypeError, df.square_value, self.false_int)
Você pode criar seu próprio
contextmanager
para verificar se a exceção foi gerada.E então você pode usar
raises
assim:Se você estiver usando
pytest
, isso já está implementado. Você pode fazerpytest.raises(Exception)
:Exemplo:
E o resultado:
fonte
unittest
módulo!Eu uso o doctest [1] em quase todos os lugares porque gosto do fato de documentar e testar minhas funções ao mesmo tempo.
Dê uma olhada neste código:
Se você colocar este exemplo em um módulo e executá-lo na linha de comando, os dois casos de teste serão avaliados e verificados.
[1] Documentação do Python: 23.2 doctest - Testar exemplos interativos do Python
fonte
Acabei de descobrir que a biblioteca Mock fornece um método assertRaisesWithMessage () (em sua subclasse unittest.TestCase), que verificará não apenas se a exceção esperada foi levantada, mas também com a mensagem esperada:
fonte
Há muitas respostas aqui. O código mostra como podemos criar uma exceção, como podemos usar essa exceção em nossos métodos e, finalmente, como você pode verificar em um teste de unidade, as exceções corretas sendo levantadas.
fonte
Você pode usar assertRaises do módulo mais unittest
fonte
Embora todas as respostas estejam perfeitamente corretas, eu estava procurando uma maneira de testar se uma função gerava uma exceção sem depender de estruturas de teste de unidade e sem precisar escrever classes de teste.
Acabei escrevendo o seguinte:
E falha na linha certa:
fonte