6
votes

Python 3 Unittest simuler l'entrée de l'utilisateur

Comment puis-je simuler la saisie de l'utilisateur au milieu d'une fonction appelée par un test d'unité (à l'aide de Python 3's Unitest)? Par exemple, j'ai une fonction foo () qui est la sortie que je teste. Dans la fonction FOO () , il demande une entrée utilisateur:

x = entrée (msg)

et la sortie est basée sur l'entrée:

Imprimer ("entrée: {0}". Format (x))

Je voudrais que mon test d'unité exécute foo () , entrez une entrée et comparez le résultat avec le résultat attendu.


0 commentaires

3 Réponses :


9
votes

J'ai régulièrement ce problème lorsque j'essaie de tester le code qui apporte des dialogues pour la saisie de l'utilisateur, et la même solution doit fonctionner pour les deux. Vous devez fournir une nouvelle fonction lié au nom entrée dans votre péril de test avec la même signature que la fonction Standard Fonction de la fonction qui renvoie simplement une valeur de test sans demander à l'utilisateur. . Selon la manière dont vos tests et vos tests sont configurés, cette injection peut être effectuée de plusieurs manières, donc je laisserai cela comme un exercice pour le lecteur, mais votre méthode de remplacement sera quelque chose de simple comme: xxx

Évidemment, vous pourriez également allumer le contenu du message si cela était pertinent et renvoyez le type de données de votre choix de votre choix. Vous pouvez également faire quelque chose de plus flexible et général qui permet de réutiliser la même méthode de remplacement dans un certain nombre de situations: xxx

et ensuite vous injecterais une fonction partielle dans entrée : xxx

quitter test_input_a et test_input_b comme des fonctions qui prennent un seul message " / Code> Argument, avec l'argument Reveal déjà lié.


2 commentaires

J'ai fini par faire quelque chose de similaire à cela. J'ai créé une fonction Test_Input "Test_input (MSG)" qui remplacerait le comportement par défaut de l'entrée sur le module que je teste: "module.input = test_input". Je définit la valeur d'entrée simulée avec une variable globale "Sample_Input" défini avant la fonction Test_Input et défini avant chaque cas de test.


Pouvez-vous fournir un exemple de comment faire l'injection avec la fonction foo fourni dans la question? Je ne peux pas comprendre comment l'obtenir correctement.



4
votes

avoir des difficultés à tester certains composants en raison de dépendances, il s'agit généralement d'un signe de mauvais design. Votre fonction FOO code> ne doit pas dépendre de la fonction globale de l'entrée code> code>, mais plutôt d'un paramètre. Ensuite, lorsque vous exécutez le programme dans un environnement de production, vous filez les choses de manière à ce que le foo code> soit appelé à l'aide de ce que entrée code> retourne. Donc, FOO code> devrait lire:

def foo(input):
    # do something with input


4 commentaires

Peut-être, mais quelque part , quelqu'un rassemble cette contribution. Lorsque vous souhaitez tester la méthode qui le faisait, vous devrez soit recourir à des outils de test fonctionnels qui manipulent une interface utilisateur à tester à ce niveau, ou faire une certaine injection. Bien sûr, vous devriez également faire des tests fonctionnels qui manipule l'interface utilisateur, mais il faut utiliser simplement pour tester l'interface utilisateur (par exemple, cette entrée () prend l'entrée que vous avez fournie) et ne pas avoir de défaillances saignées dans la terre des détails de la mise en œuvre non-UI. .


Nick, si le système à tester est une application héritée, dans laquelle le refactoring est très difficile ou qu'il faut du temps pour le faire, mais vous voulez vraiment avoir des tests de caractérisation (qui soutiendrez réellement refactoring), alors oui, je voudrais Utilisez votre méthode. Mais si la demande est en cours de développement, elle devrait être refactable afin que les tests d'unités soient faciles à écrire.


@Nick Bastin: "Peut-être, mais quelque part, quelqu'un rassemble cette entrée. Lorsque vous souhaitez tester la méthode qui fait cela ..." Le foo (entrée) est-ce. Il n'y a pas de "quelque part" d'autre que cela doit être testé.


@ S.Lott: Je ne sais pas pourquoi vous pensez que le code qui appelle l'appel d'entrée de la bibliothèque standard n'a pas besoin d'être testé. Oui, dans ce cas super trivial , ce code pourrait simplement appeler l'entrée et appeler votre méthode FOO (entrée), mais de nombreuses instances d'interaction utilisateur ne sont-elles pas aussi simples. (Et vous avez évidemment besoin de tester ce code par l'intermédiaire de la manipulation de l'interface utilisateur).



3
votes

Je pense que la meilleure approche consiste à envelopper la fonction d'entrée sur une fonction personnalisée et de moquer de ce dernier. Juste comme décrit ici: Python Entrée RAW in Unditest


0 commentaires