Comment tester la sortie STDOUT d'un script Python avec un cadre de test telle que doctest, unitest, nez, etc.? Par exemple, dirigez-vous en exécutant mon script "toDo.py -List" devrait renvoyer "Slip the Garbage". P>
J'ai lu quelqu'un qui sépare la partie d'impression STDOUT du script de la pièce qui génère la sortie à imprimer. Je suis habitué à saupoudrer des déclarations d'impression tout autour de mes scripts shell. Est-ce simplement une habitude hostile de TDD, je devrais casser ou existe un moyen de tester facilement la sortie d'impression correcte? P>
5 Réponses :
Voici quelque chose que j'ai écrit une soirée qui teste le script fonctionne. Notez que le test couvre les cas de base, mais il n'est pas suffisamment approfondi d'être un pas d'autre. Considérez-le un premier projet.
#!/usr/bin/env python # zs - some example Python code to demonstrate to Z??s # interviewers that the writer really does know Python import sys from itertools import * usage = ''' Usage: zs <string> <pattern> <n>" print top n matches of pattern in substring" ''' if sys.hexversion > 0x03000000: print "This script is only intended to run on Python version 2" sys.exit(2) if len(sys.argv) != 4: print usage sys.exit(1) A = sys.argv[1] # string to be searched B = sys.argv[2] # pattern being searched for N = sys.argv[3] # number of matches to report if not N.isdigit(): print "<n> must be a number" print usage sys.exit(3) def matchscore(s1, s2): ''' a helper function to calculate the match score ''' matches = 0 for i in xrange(len(s1)): if s1[i] == s2[i]: matches += 1 return (matches + 0.0) / len(s1) # added 0.0 to force floating point div def slices(s, n): ''' this is a generator that returns the sequence of slices of the input string s that are n characters long ''' slen = len(s) for i in xrange(slen - n + 1): yield s[i:i+n] matchlen = len(B) allscores = ((matchscore(x,B),x,i) for i,x in enumerate(slices(A,matchlen))) nonzeros = [ y for y in allscores if y[0] != 0 ] for elem in sorted(nonzeros,key=lambda e: e[0],reverse=True): nprinted = 0 # We will count them; in case num elements > N print elem[1], str(round(elem[0],4)), elem[2] nprinted += 1 if nprinted >= N: break
Je vois de deux manières:
Rediriger stdout lors de l'intention: p>
Utilisez un enregistreur pour vos sorties et écoutez-la dans votre test. P> LI>
ol> p>
Lorsque vous utilisez Py.Test pour vos tests. Vous pouvez utiliser les arguments de la fonction de test "capsys" ou "capfd" pour exécuter des affirmations contre STDOUT et STDIN
def test_myoutput(capsys): # or use "capfd" for fd-level print ("hello") sys.stderr.write("world\n") out, err = capsys.readouterr() assert out == "hello\n" assert err == "world\n" print "next" out, err = capsys.readouterr() assert out == "next\n"
Je souhaiterai peut-être aussi regarder le TextTest Cadre de test. Il se concentre davantage sur les tests fonctionnels / acceptés (de sorte que les tests unitaires) et repose fortement sur la sortie textuelle d'un programme. De cette façon, votre habitude devient une bonne: -). P>
La propre suite de test de Python le fait beaucoup, et nous utilisons deux techniques principales:
Redirection de stdout (comme d'autres ont suggéré). Nous utilisons un gestionnaire de contexte pour cela: p>
Utilisation du module code> sous-processus code>. Nous utilisons cela lorsque nous souhaitons spécifiquement tester la gestion des arguments de ligne de commande. Voir http://hg.python.org/cpython/file/ Par défaut / LIB / TEST / TEST_CMD_LINE_Script.py Pour plusieurs exemples. P> LI>
ol> p>
Ce code ne fonctionne pas sur Python 2.7. Voir . Je l'ai eu pour travailler à l'aide de la classe Stringio à partir du module B> Stringio.
Doctest sait déjà comment gérer la production ...
D'abord. Recherche: Stackoverflow.com/questions/3481561/ ... . Seconde. Recherche: La documentation Doctest ( docs.python.org/ Bibliothèque / ... ) dit "La sortie to stdout est capturée, mais pas sortie à stardr".