Comment puis-je voir la sortie d'impression normale créée pendant l'exécution pytest?

Parfois, je veux juste insérer quelques énoncés imprimés dans mon code, et voir ce qui est imprimé quand je l'exerce. Ma façon habituelle de "s'exercer" c'est avec les tests pytest existants. Mais quand je les exécute, Je ne semble pas capable de voir une sortie standard (au moins depuis PyCharm, mon IDE).

y a-t-il un moyen simple de voir la sortie standard lors d'un essai pytest?

198
demandé sur Alex Makarenko 2013-01-18 22:14:38

5 réponses

Le -s switch désactive, par examen de la capture.

271
répondu hpk42 2013-01-23 03:13:07

Dans un upvoted commentaire à la accepté de répondre , Joe , demande:

Existe-t-il un moyen d'imprimer sur la console et de capturer la sortie pour qu'elle apparaisse dans le rapport junit?

En UNIX, ce qui est communément appelé aire . Idéalement, le coup plutôt que de la capture serait le py.test par défaut. Pas idéalement, ni py.test ni aucun tiers existant py.plugin de test (... que je connais, de toute façon ) supporte teeing – malgré Python supportant trivialement teeing out-of-the-box .

le Singe de correction py.test à faire rien "1519300920 non pris en charge" est non-trivial. Pourquoi? Parce que:

  • Plus py.la fonctionnalité de test est verrouillée derrière un _pytest colis Non destiné à être importé de l'extérieur. Si vous tentez de le faire sans savoir ce que vous faites, le paquet public pytest génère des exceptions obscures à l'exécution. Merci beaucoup, py.test. Une architecture vraiment robuste que vous avez là.
  • même si vous do comprendre comment Monkey-patch le privé _pytest API dans un de manière sécuritaire, vous devez le faire avant exécution publique pytest package géré par l'extérieur "151960920 de la commande". Vous ne peut pas faire cela dans un plugin (par exemple, un module conftest de haut niveau dans votre suite de test). Par les temps py.tester paresseusement obtient autour d'importer dynamiquement votre plugin, n'importe quel py.classe de test que vous avez voulu singe-patch a été instancié depuis longtemps – et vous ne pas avoir accès à ce instance. Cela implique que, si vous voulez que votre Monkey-patch soit appliqué correctement, vous ne pouvez plus exécuter en toute sécurité la commande externe py.test . Au lieu de cela, vous devez envelopper le fonctionnement de cette commande avec un setuptools personnalisé test commande que (dans l'ordre):
    1. Singe-les patches, les privé _pytest de l'API.
    2. appelle le public pytest.main() fonction pour exécuter la commande py.test .

Cette réponse singe-patchs py.test -s et --capture=no options pour capturer stderr mais pas stdout. Par défaut, ces options ne capturent ni stderr ni stdout. Ce n'est pas tout à fait tonitruant, bien sûr. Mais chaque grand voyage commence par une préquelle fastidieuse que tout le monde oublie en cinq ans.

Pourquoi faire cela? Je vais maintenant vous dire. Mon py.la suite test-driven contient des tests fonctionnels lents. L'affichage de la sortie standard (stdout) de ces tests est utile et rassurant, empêchant leycec d'atteindre pour killall -9 py.test quand encore un autre test fonctionnel en cours échoue à faire quoi que ce soit pendant des semaines. L'affichage du stderr de ces tests, cependant, empêche py.test à partir du rapport d'exception tracebacks sur les échecs d'essai. Ce qui est complètement inutile. Par conséquent, nous imposons py.test de capture stderr, mais pas stdout.

la réponse suppose que vous avez déjà une commande de setuptools personnalisée test invoquant py.test. Si vous ne le faites pas, consultez la sous-section "intégration manuelle de py.test bien écrit bonnes pratiques page.

Do not install pytest-runner , un plugin tiers setuptools fournissant un setuptools personnalisé test le commandement invoque aussi py.test. Si pytest-runner est déjà installé, vous aurez probablement besoin de désinstaller ce paquet pip3 et ensuite d'adopter l'approche manuelle liée à ci-dessus.

en supposant que vous avez suivi les instructions de intégration manuelle mises en évidence ci-dessus, votre base de codes devrait maintenant contenir une méthode PyTest.run_tests() . Modifier cette méthode pour qu'elle ressemble à:

class PyTest(TestCommand):
             .
             .
             .
    def run_tests(self):
        # Import the public "pytest" package *BEFORE* the private "_pytest"
        # package. While importation order is typically ignorable, imports can
        # technically have side effects. Tragicomically, that is the case here.
        # Importing the public "pytest" package establishes runtime
        # configuration required by submodules of the private "_pytest" package.
        # The former *MUST* always be imported before the latter. Failing to do
        # so raises obtuse exceptions at runtime... which is bad.
        import pytest
        from _pytest.capture import CaptureManager, FDCapture, MultiCapture

        # If the private method to be monkey-patched no longer exists, py.test
        # is either broken or unsupported. In either case, raise an exception.
        if not hasattr(CaptureManager, '_getcapture'):
            from distutils.errors import DistutilsClassError
            raise DistutilsClassError(
                'Class "pytest.capture.CaptureManager" method _getcapture() '
                'not found. The current version of py.test is either '
                'broken (unlikely) or unsupported (likely).'
            )

        # Old method to be monkey-patched.
        _getcapture_old = CaptureManager._getcapture

        # New method applying this monkey-patch. Note the use of:
        #
        # * "out=False", *NOT* capturing stdout.
        # * "err=True", capturing stderr.
        def _getcapture_new(self, method):
            if method == "no":
                return MultiCapture(
                    out=False, err=True, in_=False, Capture=FDCapture)
            else:
                return _getcapture_old(self, method)

        # Replace the old with the new method.
        CaptureManager._getcapture = _getcapture_new

        # Run py.test with all passed arguments.
        errno = pytest.main(self.pytest_args)
        sys.exit(errno)

pour permettre ce singe-patch, exécutez py.essai comme suit:

python setup.py test -a "-s"

Stderr, mais pas stdout va maintenant être capturé. Chouette!

extension de la patch de singe ci-dessus à tee stdout et stderr est laissé comme un exercice pour le lecteur avec un baril-plein de temps libre.

37
répondu Cecil Curry 2016-08-02 18:27:55

selon documentation pytest , la version 3 de pytest peut désactiver temporairement la capture dans un test:

def test_disabling_capturing(capsys):
    print('this output is captured')
    with capsys.disabled():
        print('output not captured, going directly to sys.stdout')
    print('this output is also captured')
18
répondu Roman Susi 2017-01-08 13:38:22

lors de l'exécution du test, utilisez l'option -s . Toutes les instructions d'impression dans exampletest.py seraient imprimées sur la console lorsque le test est exécuté.

py.test exampletest.py -s
13
répondu Summerfun 2016-02-04 17:48:49

Essayer pytest -s -v test_login.py pour plus d'infos dans la console.

-v c'est un court. --verbose

-s signifie "désactiver la capture'



6
répondu Alex Makarenko 2018-08-08 15:46:06