web-dev-qa-db-fra.com

Comment imprimer sur console en pytest?

J'essaie d'utiliser TDD (développement piloté par les tests) avec pytest. pytest ne sera pas print sur la console lorsque j'utilise print.

J'utilise pytest my_tests.py pour l'exécuter.

La documentation semble indiquer que cela devrait fonctionner par défaut: http://pytest.org/latest/capture.html

Mais:

import myapplication as tum

class TestBlogger:

    @classmethod
    def setup_class(self):
        self.user = "alice"
        self.b = tum.Blogger(self.user)
        print "This should be printed, but it won't be!"

    def test_inherit(self):
        assert issubclass(tum.Blogger, tum.Site)
        links = self.b.get_links(posts)
        print len(links)   # This won't print either.

Rien ne s'imprime sur ma console de sortie standard (uniquement la progression normale et le nombre de tests réussis/échoués).

Et le script que je teste contient print:

class Blogger(Site):
    get_links(self, posts):
        print len(posts)   # It won't get printed in the test.

Dans le module unittest, tout est imprimé par défaut, ce qui est exactement ce dont j'ai besoin. Cependant, je souhaite utiliser pytest pour d'autres raisons.

Quelqu'un sait-il comment faire en sorte que les déclarations imprimées soient affichées?

120
BBedit

Par défaut, py.test capture le résultat de la sortie standard afin qu'il puisse contrôler la façon dont il est imprimé. Si cela ne fonctionnait pas, cela générerait beaucoup de texte sans le contexte du test imprimé.

Toutefois, si un test échoue, il inclura une section dans le rapport résultant indiquant ce qui a été imprimé conformément à la norme dans ce test particulier.

Par exemple,

def test_good():
    for i in range(1000):
        print(i)

def test_bad():
    print('this should fail!')
    assert False

Résultats dans la sortie suivante:

>>> py.test tmp.py
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items

tmp.py .F

=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________

    def test_bad():
        print('this should fail!')
>       assert False
E       assert False

tmp.py:7: AssertionError
------------------------------- Captured stdout --------------------------------
this should fail!
====================== 1 failed, 1 passed in 0.04 seconds ======================

Notez la section Captured stdout.

Si vous souhaitez voir les instructions print au fur et à mesure de leur exécution, vous pouvez passer l'indicateur -s à py.test. Cependant, notez que cela peut parfois être difficile à analyser.

>>> py.test tmp.py -s
============================= test session starts ==============================
platform darwin -- Python 2.7.6 -- py-1.4.20 -- pytest-2.5.2
plugins: cache, cov, pep8, xdist
collected 2 items

tmp.py 0
1
2
3
... and so on ...
997
998
999
.this should fail!
F

=================================== FAILURES ===================================
___________________________________ test_bad ___________________________________

    def test_bad():
        print('this should fail!')
>       assert False
E       assert False

tmp.py:7: AssertionError
====================== 1 failed, 1 passed in 0.02 seconds ======================
151
tbekolay

L'utilisation de l'option -s imprimera le résultat de toutes les fonctions, ce qui peut être trop.

Si vous avez besoin de résultats particuliers, la page de documentation que vous avez mentionnée offre quelques suggestions:

  1. Insérez assert False, "dumb assert to make PyTest print my stuff" à la fin de votre fonction et vous verrez votre sortie en raison d’un échec du test.

  2. PyTest vous a transmis un objet spécial et vous pouvez écrire la sortie dans un fichier pour l'inspecter ultérieurement, comme

    def test_good1(capsys):
        for i in range(5):
            print i
        out, err = capsys.readouterr()
        open("err.txt", "w").write(err)
        open("out.txt", "w").write(out)
    

    Vous pouvez ouvrir les fichiers out et err dans un onglet séparé et laisser l’éditeur l’actualiser automatiquement, ou exécuter une simple commande py.test; cat out.txt Shell pour exécuter votre test.

C’est une façon plutôt rigoureuse de faire des choses, mais c’est peut-être ce dont vous avez besoin: après tout, TDD signifie que vous jouez avec des choses et que vous les laissez propres et silencieuses quand elles sont prêtes :-).

45
dmitry_romanov

Réponse courte

Utilisez l'option -s:

pytest -s

Réponse détaillée

De les docs :

Pendant l'exécution du test, toute sortie envoyée à stdout et à stderr est capturée. Si un test ou une méthode de configuration échoue, sa sortie capturée sera généralement affichée avec le suivi des défaillances.

pytest a l'option --capture=method dans lequel method est une méthode de capture par test et peut être l'un des suivants: fd, sys ou no. pytest a également l'option -s qui est un raccourci pour --capture=no, et cette option vous permettra de voir vos instructions d'impression dans la console.

pytest --capture=no     # show print statements in console
pytest -s               # equivalent to previous command

Définition de méthodes de capture ou désactivation de la capture

pytest peut effectuer la capture de deux manières:

  1. capture de niveau de descripteur de fichier (FD) (par défaut): toutes les écritures destinées aux descripteurs de fichier du système d'exploitation 1 et 2 seront capturées.

  2. capture de niveau sys : seules les écritures dans Python fichiers _sys.stdout et sys.stderr seront capturées. Aucune capture des écritures dans les archives de fichiers n'est effectuée.

pytest -s            # disable all capturing
pytest --capture=sys # replace sys.stdout/stderr with in-mem files
pytest --capture=fd  # also point filedescriptors 1 and 2 to temp file
13
lmiguelvargasf

J'avais besoin d'imprimer un avertissement important concernant les tests ignorés au moment exact où PyTest était coupé littéralement tout.

Je ne voulais pas échouer à un test pour envoyer un signal, alors j'ai fait un hack comme suit:

def test_2_YellAboutBrokenAndMutedTests():
    import atexit
    def report():
        print C_patch.tidy_text("""
In silent mode PyTest breaks low level stream structure I work with, so
I cannot test if my functionality work fine. I skipped corresponding tests.
Run `py.test -s` to make sure everything is tested.""")
    if sys.stdout != sys.__stdout__:
        atexit.register(report)

Le module atexit me permet d’imprimer des choses après que PyTest ait libéré les flux de sortie. La sortie se présente comme suit:

============================= test session starts ==============================
platform linux2 -- Python 2.7.3, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
rootdir: /media/Storage/henaro/smyth/Alchemist2-git/sources/C_patch, inifile: 
collected 15 items 

test_C_patch.py .....ssss....s.

===================== 10 passed, 5 skipped in 0.15 seconds =====================
In silent mode PyTest breaks low level stream structure I work with, so
I cannot test if my functionality work fine. I skipped corresponding tests.
Run `py.test -s` to make sure everything is tested.
~/.../sources/C_patch$

Le message est imprimé même lorsque PyTest est en mode silencieux et est non imprimé si vous exécutez des commandes avec py.test -s, donc tout est déjà bien testé.

10
dmitry_romanov

Selon le pytest docs , pytest --capture=sys devrait fonctionner. Si vous souhaitez capturer la norme dans un test, reportez-vous à la page d’installation de Capsys.