Pytest: Comment tester une fonction de saisie de l'appel?
J'ai une console de programme écrit en Python. Il demande à l'utilisateur de questions à l'aide de la commande:
some_input = input('Answer the question:', ...)
Comment pourrais-je tester une fonction contenant un appel à input
à l'aide de pytest
?
Je ne voudrais pas forcer un testeur de saisie de texte à plusieurs reprises seulement de terminer une série de tests.
- Avez-vous regarder à travers des tutoriels sur la façon d'utiliser
pytest
pour voir ce que vous pouvez essayer? C'est une assez vaste question à se poser. - Pas récemment. J'ai utilisé pytest avant, mais il est venu à mon esprit quand penser à faire du TDD pour mon projet ici et je n'ai aucune idée de comment le résoudre. Je vais jeter un oeil à ceux-tuts de nouveau.
- Dans votre fonction de test, vous pouvez réaffecter les
input()
la fonction de quelque chose d'autre (aussi connu comme "monkey patching" ou de "shadowing"). - Pas une mauvaise idée, qui pourrait être la voie.
- Relative (sans doublon): stackoverflow.com/questions/6271947/...
Vous devez vous connecter pour publier un commentaire.
Vous devriez probablement se moquer de l'intégré dans
entrée
fonction, vous pouvez utiliser lepermutation
fonctionnalités fournies parpytest
pour revenir à l'originalinput
fonction après chaque test.Une solution plus élégante serait d'utiliser la
faux
module avec unavec l'instruction
. De cette façon, vous n'avez pas besoin d'utiliser le démontage et le patché méthode ne pourra vivre dans lawith
portée.input
pour l'ensemble de la session de test, ou seulement pour ce un test?input
pour quoi que ce soit en cours d'exécution après ce test. Vous devez utiliser à la place pytest du monkeypatch luminaire à l'inverse automatiquement les correctifs à la fin de l'essai.__builtins__
pas__builtin__
Que Le Compilateur a suggéré, pytest a une nouvelle monkeypatch luminaire pour cela. Un monkeypatch objet peut modifier un attribut dans une classe ou une valeur dans un dictionnaire, puis de restaurer sa valeur d'origine à la fin de l'essai.
Dans ce cas, le haut-
input
fonction est une valeur de python__builtins__
dictionnaire, on peut donc le modifier comme suit:setattr
, passetitem
.Vous pouvez remplacer
sys.stdin
avec quelques personnalisé Texte IO, comme les entrées à partir d'un fichier ou d'un mémoire StringIO tampon:c'est plus robuste que seuls les correctifs
input()
, tant que cela ne sera pas suffisant si le module utilise des autres modes de consommation de texte à partir de stdin.Cela peut aussi être fait assez élégamment avec un gestionnaire de contexte
Et puis il suffit de l'utiliser comme ceci par exemple:
Vous pouvez le faire avec
mock.patch
comme suit.Tout d'abord, dans votre code, créer un mannequin de fonction pour les appels à
input
:Dans vos fonctions de test:
Par exemple, si vous avez une boucle de vérifier que les seules réponses valables sont dans ['y', 'Y', 'n', 'N'] vous pouvez tester que rien ne se passe lors de la saisie d'une valeur différente à la place.
Cela peut être fait avec
mock.patch
etwith
blocs en python3.La ligne de la note est
mock.patch.object(builtins, 'input', lambda _: '19'):
, qui remplace lainput
avec la fonction lambda. Notre fonction lambda prend dans une poubelle variable_
parce queinput
prend en argument.Voici comment vous pouvez tester les cas d'échec, où user_input appels
sys.exit
. L'astuce ici est d'obtenir pytest à regarder pour que l'exceptionpytest.raises(SystemExit)
.Vous devriez être en mesure d'obtenir ce test en cours d'exécution par copier et de coller le code ci-dessus dans un fichier
tests/test_.py
et en cours d'exécutionpytest
du parent dir.