Est-il possible pour un test unitaire d'affirmer qu'une méthode appelle sys.exit ()

98

J'ai une méthode python 2.7 qui appelle parfois

sys.exit(1) 

Est-il possible de faire un test unitaire qui vérifie que cette ligne de code est appelée lorsque les bonnes conditions sont remplies?

Travis Bear
la source
Copie
AGK

Réponses:

155

Oui. sys.exitaugmente SystemExit, vous pouvez donc le vérifier avec assertRaises:

with self.assertRaises(SystemExit):
    your_method()

Les instances de SystemExitont un attribut codequi est défini sur le statut de sortie proposé, et le gestionnaire de contexte renvoyé par assertRaisesa l'instance d'exception capturée comme exception, donc vérifier le statut de sortie est facile:

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

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

 

Documentation sys.exit :

Quittez Python. Ceci est implémenté en levant l' SystemExitexception ... il est possible d'intercepter la tentative de sortie à un niveau externe.

Pavel Anossov
la source
3
+1, sauf que s'il veut vérifier qu'il appelle sys.exit(1)(par opposition à, disons, sys.exit(0)) vous devez en fait affirmer que codec'est 1. Je suppose que vous pourriez le faire avec assertRaisesRegexp(SystemExit, '1')?
abarnert
J'étais sûr qu'il y avait une unittestméthode qui vous permet de passer une exception et un prédicat appelable à exécuter sur l'exception ou ses arguments, plutôt qu'un simple motif regex à exécuter sur la représentation sous forme de chaîne de son premier argument… mais je suppose que non. Y a-t-il un autre module de test auquel je pense?
abarnert
1
+1, en ce qui concerne la vérification du code d'erreur, il est beaucoup plus simple de le faire: self.assertRaisesRegex( SystemExit, '^2$', testMethod ) moins de code, assez lisible.
Marek Lewandowski
1
@MarekLewandowski - faute de frappe. Doit êtreself.assertRaisesRegexp
Evgen
12

Voici un exemple de travail complet. En dépit de l'excellente réponse de Pavel, il m'a fallu un certain temps pour comprendre cela, donc je l'inclus ici dans l'espoir que ce sera utile.

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)
Travis Bear
la source
3

J'ai trouvé la réponse à votre question dans la recherche de documentation Python Unit Testing pour "Testing for Exceptions". En utilisant votre exemple, le test unitaire ressemblerait à ceci:

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

N'oubliez pas d'inclure tous les arguments nécessaires pour tester votre fonction.

somnolent
la source
1

En guise de note supplémentaire à l'excellente réponse de Pavel, vous pouvez également vérifier les statuts spécifiques s'ils sont fournis dans la fonction que vous testez. Par exemple, s'il your_method()contenait ce qui suit, sys.exit("Error")il serait possible de tester spécifiquement "Erreur":

with self.assertRaises(SystemExit) as cm:
    your_method()
    self.assertEqual(cm.exception, "Error")
substrat binaire
la source