unittest unit tests test skipif modules examples python unit-testing logging pydev

python - tests - Prueba unitaria PyDev: Cómo capturar texto registrado en un registro. Iniciador en "Salida capturada"



unit test en python (4)

El problema es que el sys.stdout unittest reemplaza sys.stdout / sys.stderr antes de que sys.stderr la prueba, y StreamHandler todavía está escribiendo en el sys.stdout original.

Si asigna el ''actual'' sys.stdout al controlador, debería funcionar (vea el código a continuación).

import sys import unittest import logging logger = logging.getLogger() logger.level = logging.DEBUG stream_handler = logging.StreamHandler(sys.stdout) logger.addHandler(stream_handler) class TestCase(unittest.TestCase): def testSimpleMsg(self): stream_handler.stream = sys.stdout print("AA") logging.getLogger().info("BB")

Sin embargo, un mejor enfoque sería agregar / eliminar el controlador durante la prueba:

import sys import unittest import logging logger = logging.getLogger() logger.level = logging.DEBUG class TestCase(unittest.TestCase): def testSimpleMsg(self): stream_handler = logging.StreamHandler(sys.stdout) logger.addHandler(stream_handler) try: print("AA") logging.getLogger().info("BB") finally: logger.removeHandler(stream_handler)

Estoy usando PyDev para desarrollo y pruebas unitarias de mi aplicación Python. En cuanto a las pruebas unitarias, todo funciona en gran medida por el hecho de que el contenido se haya registrado en cualquier registro. Logger no es capturado por la "Salida capturada" de PyDev.

Ya reenvío todo lo registrado a la salida estándar de esta manera:

import sys logger = logging.getLogger() logger.level = logging.DEBUG logger.addHandler(logging.StreamHandler(sys.stdout))

Sin embargo, la "Salida capturada" no muestra las cosas registradas en los registradores.

Aquí un ejemplo unittest-script: test.py

import sys import unittest import logging logger = logging.getLogger() logger.level = logging.DEBUG logger.addHandler(logging.StreamHandler(sys.stdout)) class TestCase(unittest.TestCase): def testSimpleMsg(self): print("AA") logging.getLogger().info("BB")

La salida de la consola es:

Finding files... done. Importing test modules ... done. testSimpleMsg (itf.lowlevel.tests.hl7.TestCase) ... AA 2011-09-19 16:48:00,755 - root - INFO - BB BB ok ---------------------------------------------------------------------- Ran 1 test in 0.001s OK

Pero la SALIDA CAPTURADA para la prueba es:

======================== CAPTURED OUTPUT ========================= AA

¿Alguien sabe cómo capturar todo lo que se registra en un logging.Logger durante la ejecución de esta prueba?


Me cansé de tener que agregar manualmente el gran código de Fabio a todos los setUp , así que __metaclass__ unittest.TestCase con algunos __metaclass__ ing:

class LoggedTestCase(unittest.TestCase): __metaclass__ = LogThisTestCase logger = logging.getLogger("unittestLogger") logger.setLevel(logging.DEBUG) # or whatever you prefer class LogThisTestCase(type): def __new__(cls, name, bases, dct): # if the TestCase already provides setUp, wrap it if ''setUp'' in dct: setUp = dct[''setUp''] else: setUp = lambda self: None print "creating setUp..." def wrappedSetUp(self): # for hdlr in self.logger.handlers: # self.logger.removeHandler(hdlr) self.hdlr = logging.StreamHandler(sys.stdout) self.logger.addHandler(self.hdlr) setUp(self) dct[''setUp''] = wrappedSetUp # same for tearDown if ''tearDown'' in dct: tearDown = dct[''tearDown''] else: tearDown = lambda self: None def wrappedTearDown(self): tearDown(self) self.logger.removeHandler(self.hdlr) dct[''tearDown''] = wrappedTearDown # return the class instance with the replaced setUp/tearDown return type.__new__(cls, name, bases, dct)

Ahora su caso de prueba simplemente puede heredar de LoggedTestCase , es decir, la class TestCase(LoggedTestCase) lugar de la class TestCase(unittest.TestCase) y listo. Alternativamente, puede agregar la línea __metaclass__ y definir el logger en la prueba o LogThisTestCase ligeramente modificado.


Me encontré con este problema también. Terminé subclasando StreamHandler y anulando el atributo de flujo con una propiedad que obtiene sys.stdout. De esta forma, el controlador utilizará la secuencia que prueba la unidad. TestCase se ha cambiado a sys.stdout:

class CapturableHandler(logging.StreamHandler): @property def stream(self): return sys.stdout @stream.setter def stream(self, value): pass

A continuación, puede configurar el controlador de registro antes de ejecutar pruebas de ese modo (esto agregará el controlador personalizado al registrador de raíz):

def setup_capturable_logging(): if not logging.getLogger().handlers: logging.getLogger().addHandler(CapturableHandler())

Si, como yo, tiene sus pruebas en módulos separados, puede simplemente poner una línea después de las importaciones de cada módulo de prueba de la unidad que se asegurará de que el registro esté configurado antes de ejecutar las pruebas:

import logutil logutil.setup_capturable_logging()

Este podría no ser el enfoque más limpio, pero es bastante simple y funcionó bien para mí.