python - ¿Cómo puedo ver el resultado de impresión normal creado durante la ejecución de pytest?
logging output (5)
Algunas veces solo quiero insertar algunas declaraciones impresas en mi código y ver qué se imprime cuando lo hago. Mi forma habitual de "ejercitarlo" 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 forma sencilla de ver la salida estándar durante una ejecución de pytest?
Al ejecutar la prueba use la opción -s
. Todas las declaraciones de impresión en exampletest.py
se imprimirán en la consola cuando se ejecute la prueba.
py.test exampletest.py -s
En un comentario a favor de 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 . Lo ideal sería que el ajuste de py en lugar de la captura fuera el valor predeterminado de py.test. No idealmente, ni py.test ni ningún plugin py.test de terceros existente (... que yo sepa, de todos modos ) es compatible con el teeing, a pesar de que Python lo apoya de forma trivial out-of-the-box .
El parche de mono py.test para hacer algo sin soporte no es trivial. ¿Por qué? Porque:
- La mayoría de las funciones de py.test están bloqueadas detrás de un paquete privado
_pytest
que no está diseñado para ser importado externamente. Intentar hacerlo sin saber lo que está haciendo normalmente resulta en que el paquete público depytest
excepciones pocopytest
en el tiempo de ejecución. Muchas gracias, py.test. Arquitectura realmente robusta que tienes allí. - Incluso cuando
_pytest
cómo realizar una revisión_pytest
API_pytest
privada, debes hacerlo antes de ejecutar el paquete públicopytest
ejecutado por el comando externopy.test
. No puede hacer esto en un complemento (por ejemplo, un móduloconftest
nivelconftest
en su conjunto de pruebas). En el momento en que py.test perezosamente pasa a importar dinámicamente su complemento, cualquier clase de py.test que deseaba hacer un parche hace mucho tiempo que ha sido instanciada, 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 comando externopy.test
. En su lugar, tiene que envolver la ejecución de ese comando con un comando detest
setuptools personalizado que (en orden):- Monkey-parches la API
_pytest
privada. - Llama a la función pública
pytest.main()
para ejecutar el comandopy.test
.
- Monkey-parches la API
Esta respuesta monkey-patches py.test''s -s
y --capture=no
opciones para capturar stderr pero no stdout. Por defecto, estas opciones no capturan ni stderr ni stdout. Esto no está del todo bien, por supuesto. Pero cada gran viaje comienza con una precuela tediosa que todos olvidan en cinco años.
¿Por qué hacer esto? Ahora te diré. Mi conjunto de pruebas py.test-driven contiene pruebas funcionales lentas. Mostrar el stdout de estas pruebas es útil y tranquilizador, ya que evita que leycec alcance la leycec de killall -9 py.test
cuando otra prueba funcional de larga duración no puede hacer nada durante semanas. Sin embargo, la visualización del historial de estas pruebas evita que py.test informe las trazas de excepción en caso de fallas de prueba. Lo cual es completamente inútil. Por lo tanto, forzamos py.test para capturar stderr pero no stdout.
Antes de llegar a ella, esta respuesta asume que ya tiene un comando de test
setuptools personalizado que invoca py.test. Si no lo hace, consulte la subsección Integración manual de la página de Buenas Prácticas de py.test.
No instale pytest-runner , un complemento setuptools de terceros que proporciona un comando de test
setuptools personalizado que también invoca py.test. Si pytest-runner ya está instalado, probablemente necesitará desinstalar ese paquete pip3 y luego adoptar el enfoque manual vinculado a lo anterior.
Suponiendo que siguió las instrucciones en la Integración manual resaltada anteriormente, su base de código ahora debería contener un método PyTest.run_tests()
. Modificar 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"
Stderr pero no stdout ahora será capturado. ¡Hábil!
Extender el parche de mono anterior a la salida de la partida y el stderr se deja como un ejercicio para el lector con un barril lleno de tiempo libre.
Pruebe pytest -s -v test_login.py
para obtener más información en la consola.
-v
es un corto --verbose
-s
significa ''deshabilitar toda captura''
Según la documentación de pytest , la versión 3 de pytest puede inhabilitar 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'')
El interruptor -s
desactiva la captura por prueba.