¿Cómo imprimo en la consola en pytest?

Resuelto BBedit asked hace 10 años • 12 respuestas

pytestno imprimirá en la consola cuando uso print. La documentación parece decir que debería funcionar de forma predeterminada.

Estoy usando pytest my_tests.pypara ejecutar esta prueba:

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.

No se imprime nada en mi consola de salida estándar (solo el progreso normal y cuántas pruebas pasaron/fallaron).

Y el script que estoy probando contiene print:

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

En unittestel módulo, todo se imprime de forma predeterminada, que es exactamente lo que necesito. Sin embargo, deseo utilizarlo pytestpor otras razones.

¿Alguien sabe cómo hacer que se muestren las declaraciones impresas?

BBedit avatar Jul 08 '14 01:07 BBedit
Aceptado

De forma predeterminada, py.testcaptura el resultado de la salida estándar para poder controlar cómo lo imprime. Si no hiciera esto, arrojaría una gran cantidad de texto sin el contexto de qué prueba imprimió ese texto.

Sin embargo, si una prueba falla, se incluirá una sección en el informe resultante que muestra lo que se imprimió según el estándar en esa prueba en particular.

Por ejemplo,

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

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

Da como resultado el siguiente resultado:

>>> 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 ======================

Tenga en cuenta la Captured stdoutsección.

Si desea ver printlas declaraciones a medida que se ejecutan, puede pasar la -sbandera a py.test. Sin embargo, tenga en cuenta que a veces esto puede resultar difícil de analizar.

>>> 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 ======================
tbekolay avatar Jul 07 '2014 18:07 tbekolay

Utilice la -sopción:

pytest -s

Respuesta detallada

De los documentos :

Durante la ejecución de la prueba , se captura cualquier salida enviada a stdout y stderr . Si una prueba o un método de configuración falla, el resultado capturado correspondiente generalmente se mostrará junto con el seguimiento del error.

pytesttiene la opción --capture=methodde cuál methodes el método de captura por prueba y podría ser uno de los siguientes fd: syso no. pytestTambién tiene la opción -sque es un acceso directo para --capture=no, y esta es la opción que le permitirá ver sus declaraciones impresas en la consola.

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

Configurar métodos de captura o deshabilitar la captura

Hay dos formas en las que pytestse puede realizar la captura:

  1. Captura de nivel de descriptor de archivo (FD) (predeterminado): se capturarán todas las escrituras que vayan a los descriptores de archivo 1 y 2 del sistema operativo.

  2. captura de nivel de sistema : solo se capturarán las escrituras en archivos Python sys.stdout y sys.stderr. No se realiza ninguna captura de escrituras en descriptores de archivos.

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
lmiguelvargasf avatar May 02 '2019 10:05 lmiguelvargasf

El uso -sde la opción imprimirá el resultado de todas las funciones, lo que puede ser excesivo.

Si necesita un resultado particular, la página de documentación que mencionó ofrece algunas sugerencias:

  1. Insértelo assert False, "dumb assert to make PyTest print my stuff"al final de su función y verá el resultado debido a una prueba fallida.

  2. PyTest le pasa un objeto especial y puede escribir el resultado en un archivo para inspeccionarlo más tarde, como

    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)
    

    Puede abrir los archivos outy erren una pestaña separada y dejar que el editor los actualice automáticamente, o ejecutar un simple py.test; cat out.txtcomando de shell para ejecutar la prueba.

Esa es una manera bastante hacky de hacer las cosas, pero puede ser que sean las cosas que necesitas: después de todo, TDD significa que te metes con las cosas y las dejas limpias y silenciosas cuando están listas :-).

dmitry_romanov avatar Aug 05 '2016 09:08 dmitry_romanov

Esta es la forma más limpia que conozco de imprimir una sola declaración sys.stdout(sin hacer que la prueba falle artificialmente o habilitar la -sopción): puedes ver el resultado específico que deseas y nada más:

  1. Agregue el parámetro incorporado capsysa su función de prueba. (Esto significa que agrega capsysa la lista de parámetros, por ejemplo
def test_function(existing_parameters, capsys):
  1. En su código, simplemente inserte:
with capsys.disabled():
   print("this output will not be captured and go straight to sys.stdout")

Consulte https://buildmedia.readthedocs.org/media/pdf/pytest/latest/pytest.pdf (2.11 Cómo capturar la salida stdout/stderr).

Sacha avatar May 18 '2021 05:05 Sacha

Necesitaba imprimir una advertencia importante sobre las pruebas omitidas exactamente cuando PyTestsilenciaba literalmente todo .

No quería fallar una prueba para enviar una señal, así que hice el siguiente truco:

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)

El atexitmódulo me permite imprimir cosas después de PyTest publicar los flujos de salida. El resultado tiene el siguiente aspecto:

============================= 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$

El mensaje se imprime incluso cuando PyTestestá en modo silencioso y no se imprime si ejecuta cosas con py.test -s, por lo que todo ya está probado correctamente.

dmitry_romanov avatar Aug 06 '2016 17:08 dmitry_romanov