¿Cómo puedo ver la salida de impresión normal creada durante la ejecución de pytest?

401

A veces solo quiero insertar algunas declaraciones de impresión en mi código y ver qué se imprime cuando lo ejercito. Mi forma habitual de "hacer ejercicio" es con las pruebas pytest existentes. Pero cuando ejecuto estos, no puedo ver ninguna salida estándar (al menos desde PyCharm, mi IDE).

¿Hay una manera simple de ver la salida estándar durante una ejecución de pytest?

Des
fuente
¿Solo en caso de fracaso o siempre?
17
-s deshabilita la captura por prueba
hpk42
3
@delnan - Me gustaría verlo siempre
Des

Respuestas:

51

En un comentario votado a la respuesta aceptada , Joe pregunta:

¿Hay alguna forma de imprimir en la consola Y capturar la salida para que se muestre en el informe junit?

En UNIX, esto se conoce comúnmente como teeing . Idealmente, tee en lugar de capturar sería el valor predeterminado de py.test. De forma no ideal, ni py.test ni ningún complemento de py.test de terceros existente (... que yo sepa, de todos modos ) admite el teeing, a pesar de que Python admite trivialmente el tee -out-of-the-box .

Py.test parcheado de mono para hacer cualquier cosa sin soporte no es trivial. ¿Por qué? Porque:

  • La mayoría de las funciones de py.test están bloqueadas detrás de un _pytestpaquete privado que no está destinado a ser importado externamente. Intentar hacerlo sin saber lo que está haciendo generalmente da como resultado que el pytestpaquete público genere oscuras excepciones en tiempo de ejecución. Muchas gracias, py.test. Arquitectura realmente robusta que tienes allí.
  • Incluso cuando se hace la manera de mono-privada parchear el _pytestAPI de una manera segura, usted tiene que hacerlo antes de ejecutar el público pytestejecute el paquete por el exterior py.testde comandos. No puede hacer esto en un complemento (por ejemplo, un conftestmódulo de nivel superior en su conjunto de pruebas). En el momento en que py.test perezosamente importa dinámicamente su complemento, cualquier clase de py.test que quería parchear mono hace mucho tiempo que se ha instanciado, y no tiene acceso a esa instancia. Esto implica que, si desea que su parche de mono se aplique de manera significativa, ya no puede ejecutar con seguridad el py.testcomando externo . En cambio, debe ajustar la ejecución de ese comando con herramientas de configuración personalizadastest comando que (en orden):
    1. Monkey-parches de la _pytestAPI privada .
    2. Llama a la pytest.main()función pública para ejecutar el py.testcomando.

Esta respuesta mono-parches py.test -sy --capture=noopciones para capturar stderr pero no stdout. Por defecto, estas opciones no capturan ni stderr ni stdout. Esto no es del todo bueno, por supuesto. Pero cada gran viaje comienza con una tediosa precuela que todos olvidan en cinco años.

¿Por qué hacer esto? Ahora te lo diré. Mi conjunto de pruebas controladas por py.test contiene pruebas funcionales lentas. Mostrar el stdout de estas pruebas es útil y tranquilizador, evitando que leycec alcance killall -9 py.testcuando otra prueba funcional de larga duración no puede hacer nada durante semanas. Sin embargo, mostrar el stderr de estas pruebas evita que py.test informe rastreos de excepción en fallas de prueba. Lo cual es completamente inútil. Por lo tanto, obligamos a py.test a capturar stderr pero no stdout.

Antes de llegar a él, esta respuesta asume que ya tiene un testcomando de configuración personalizada que invoca py.test. Si no lo hace, consulte la subsección de Integración manual de la página de Buenas prácticas bien escrita de py.test .

No , no instalar PYtest-corredor , un setuptools terceros plugin de proporcionar un setuptools personalizados testcomando también invocando py.test. Si pytest-runner ya está instalado, probablemente deba desinstalar ese paquete pip3 y luego adoptar el enfoque manual vinculado anteriormente.

Suponiendo que haya seguido las instrucciones en Integración manual resaltadas anteriormente, su base de código ahora debe contener un PyTest.run_tests()método. Modifique este método para parecerse a:

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)

Para habilitar este parche de mono, ejecute py.test de la siguiente manera:

python setup.py test -a "-s"

Ahora se capturará Stderr pero no stdout. ¡Hábil!

Extender el parche de monos anterior a tee stdout y stderr se deja como un ejercicio para el lector con un barril lleno de tiempo libre.

Cecil Curry
fuente
33

Al ejecutar la prueba, use la -sopción. Todas las declaraciones de impresión exampletest.pyse imprimirán en la consola cuando se ejecute la prueba.

py.test exampletest.py -s
Verano divertido
fuente
31

Según la documentación de pytest , la versión 3 de pytest puede desactivar temporalmente la captura en una prueba:

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')
Roman Susi
fuente
20

pytest captura el stdout de pruebas individuales y las muestra solo en ciertas condiciones, junto con el resumen de las pruebas que imprime por defecto.

Se puede mostrar información de resumen adicional usando la opción '-r':

pytest -rP

muestra la salida capturada de las pruebas aprobadas.

pytest -rx

muestra la salida capturada de las pruebas fallidas (comportamiento predeterminado).

El formato de la salida es más bonito con -r que con -s.

Sunthar
fuente
2
¡Esta es la respuesta real que estaba buscando! Gracias. (Hacer que la
salida estándar aparezca
18

Intenta pytest -s -v test_login.pyobtener más información en la consola.

-v es un corto --verbose

-s significa 'deshabilitar toda captura'



Alex Makarenko
fuente
1
si está usando el archivo pytest.ini puede usar: addopts = -s -v python_files = test_login.py
timj98
4

Si está utilizando PyCharm IDE, puede ejecutar esa prueba individual o todas las pruebas utilizando la barra de herramientas Ejecutar. La ventana de la herramienta Ejecutar muestra el resultado generado por su aplicación y puede ver todas las declaraciones de impresión allí como parte del resultado de la prueba.

Géminis Jain
fuente
¿Sabes cómo imprimir PyCharm mientras se ejecuta la prueba? (en lugar de después de que la prueba haya pasado)
Alexandre Huat
3

pytest --capture=tee-sysfue agregado recientemente. Puede capturar y ver la salida en stdout / err.

meonstackexchange
fuente
-4

Las otras respuestas no funcionan. La única forma de ver la salida capturada es utilizando el siguiente indicador:

pytest --show-capture all

aaa90210
fuente
66
--show-capture=alles el valor predeterminado Agregarlo no afecta nada.
hoefling