É possível para um teste de unidade afirmar que um método chama sys.exit ()

98

Eu tenho um método python 2.7 que às vezes chama

sys.exit(1) 

É possível fazer um teste de unidade que verifica se esta linha de código é chamada quando as condições certas são atendidas?

Urso Travis
fonte

Respostas:

155

Sim. sys.exitaumentos SystemExit, então você pode verificar com assertRaises:

with self.assertRaises(SystemExit):
    your_method()

As instâncias de SystemExittêm um atributo codeque é definido para o status de saída proposto e o gerenciador de contexto retornado por assertRaisespossui a instância de exceção capturada como exception, portanto, verificar o status de saída é fácil:

with self.assertRaises(SystemExit) as cm:
    your_method()

self.assertEqual(cm.exception.code, 1)

 

Documentação sys.exit :

Saia do Python. Isso é implementado levantando a SystemExitexceção ... é possível interceptar a tentativa de saída em um nível externo.

Pavel Anossov
fonte
3
+1, exceto que se ele quer para verificar que ele chama sys.exit(1)(ao contrário de, digamos, sys.exit(0)) que você precisa para realmente afirmar a sua codeé 1. Eu acho que você poderia fazer isso com assertRaisesRegexp(SystemExit, '1')?
abarnert
Eu tinha certeza de que havia um unittestmétodo que permite passar uma exceção e um predicado que pode ser chamado para executar na exceção ou em seus args, em vez de apenas um padrão regex para executar na representação de string de seu primeiro arg ... mas acho que não. Existe algum outro módulo de teste em que estou pensando?
abarnert
1
+1, quanto à verificação do código de erro, é muito mais simples fazer apenas: self.assertRaisesRegex( SystemExit, '^2$', testMethod ) Menos código, legível o suficiente.
Marek Lewandowski
1
@MarekLewandowski - typo. Deve serself.assertRaisesRegexp
Evgen
12

Aqui está um exemplo de trabalho completo. Apesar da excelente resposta de Pavel, demorei um pouco para descobrir isso, então estou incluindo aqui na esperança de que seja útil.

import unittest
from glf.logtype.grinder.mapping_reader import MapReader

INCOMPLETE_MAPPING_FILE="test/data/incomplete.http.mapping"

class TestMapReader(unittest.TestCase):

    def test_get_tx_names_incomplete_mapping_file(self):
        map_reader = MapReader()
        with self.assertRaises(SystemExit) as cm:
            tx_names = map_reader.get_tx_names(INCOMPLETE_MAPPING_FILE)
        self.assertEqual(cm.exception.code, 1)
Urso Travis
fonte
3

Encontrei a resposta para sua pergunta na documentação do Python Unit Testing, procure "Testing for Exceptions". Usando seu exemplo, o teste de unidade ficaria assim:

self.assertRaises(SystemExit, your_function, argument 1, argument 2)

Lembre-se de incluir todos os argumentos necessários para testar sua função.

sonolento
fonte
1

Como uma observação adicional à excelente resposta de Pavel, você também pode verificar se há status específicos se eles forem fornecidos na função que você está testando. Por exemplo, se your_method()contiver o seguinte sys.exit("Error"), seria possível testar especificamente para "Erro":

with self.assertRaises(SystemExit) as cm:
    your_method()
    self.assertEqual(cm.exception, "Error")
substrato binário
fonte