2011-08-24 10 views
13

que tienen un módulo de prueba en la norma unittest formatoRun Python unittest para que nada se imprime si tiene éxito, sólo se AssertionError() si falla

class my_test(unittest.TestCase): 

    def test_1(self): 
     [tests] 

    def test_2(self): 
     [tests] 
    etc.... 

Mi empresa cuenta con un instrumento de prueba de propiedad que se ejecutará mi módulo como un script de línea de comandos, y que detectará cualquier error que surja en mi módulo, pero requiere que mi módulo se silencie si tiene éxito.

Por lo tanto, estoy tratando de encontrar una manera de ejecutar mi módulo de prueba desnudo, de modo que si todas mis pruebas pasen, no se imprima nada en la pantalla, y si una prueba falla con un AssertionError, ese error se canaliza a través del pila de errores estándar de Python (al igual que cualquier otro error haría en una secuencia de comandos de Python normal.)

el docs abogan por el uso de la función unittest.main() para ejecutar todas las pruebas en un módulo dado como

if __name__ == "__main__": 
    unittest.main() 

El problema es que esto envuelve los resultados de la prueba en el arnés de prueba de unidad, de modo que incluso si todas las pruebas son exitosas, aún inserta algo de pelusa en la pantalla, y si hay un error, no es simplemente arrojado como un error típico de pitón, sino también vestido con el arnés.

He intentado redirigiendo la salida a una corriente alterna mediante

with open('.LOG','a') as logf: 
    suite = unittest.TestLoader().loadTestsFromTestCase(my_test) 
    unittest.TextTestRunner(stream = logf).run(suite) 

El problema aquí es que todo se canaliza al archivo de registro (incluyendo toda notificación de errores). Entonces, cuando el arnés de mi empresa ejecuta el módulo, se completa con éxito porque, por lo que puede ver, no se generaron errores (porque todos fueron canalizados al archivo de registro).

¿Alguna sugerencia sobre cómo puedo construir un corrector de prueba que suprima toda la pelusa y errores de canalizaciones a través de la pila de errores de Python normal? Como siempre, si crees que hay una mejor manera de abordar este problema, házmelo saber.

EDIT:

Esto es lo que terminé usando para resolver esto. En primer lugar, he añadido un "get_test_names()" método para mi clase de prueba:

class my_test(unittest.TestCase): 
    etc.... 
    @staticmethod 
    def get_test_names(): 
     """Return the names of all the test methods for this class.""" 
     test_names = [ member[0] for memeber in inspect.getmembers(my_test) 
         if 'test_' in member[0] ] 

Luego reemplacé mi llamada a unittest.main() con lo siguiente:

# Unittest catches all errors raised by the test cases, and returns them as 
# formatted strings inside a TestResult object. In order for the test 
# harness to catch these errors they need to be re-raised, and so I am defining 
# this CompareError class to do that. 
# For each code error, a CompareError will be raised, with the original error 
# stack as the argument. For test failures (i.e. assertion errors) an 
# AssertionError is raised. 
class CompareError(Exception): 
    def __init__(self,err): 
     self.err = err 
    def __str__(self): 
     return repr(self.err) 

# Collect all tests into a TestSuite() 
all_tests = ut.TestSuite() 
for test in my_test.get_test_names(): 
    all_tests.addTest(my_test(test)) 
# Define a TestResult object and run tests 
results = ut.TestResult() 
all_tests.run(results) 
# Re-raise any script errors 
for error in results.errors: 
    raise CompareError(error[1]) 
# Re-raise any test failures 
for failure in results.failures: 
    raise AssertionError(failure[1]) 

Respuesta

3

me ocurrió esto. Si puede cambiar la línea de comando, puede eliminar la redirección io interna.

import sys, inspect, traceback 

# redirect stdout, 
# can be replaced by testharness.py > /dev/null at console 
class devnull(): 
    def write(self, data): 
     pass 

f = devnull() 
orig_stdout = sys.stdout 
sys.stdout = f 

class TestCase(): 
    def test_1(self): 
     print 'test_1' 

    def test_2(self): 
     raise AssertionError, 'test_2' 

    def test_3(self): 
     print 'test_3' 


if __name__ == "__main__": 
    testcase = TestCase() 
    testnames = [ t[0] for t in inspect.getmembers(TestCase) 
         if t[0].startswith('test_') ] 

    for testname in testnames: 
     try: 
      getattr(testcase, testname)() 
     except AssertionError, e: 
      print >> sys.stderr, traceback.format_exc() 

# restore 
sys.stdout = orig_stdout 
+0

Muchas gracias, Gringo Suave. Terminé construyendo un corredor de prueba usando las clases TestSuite y TestResult, pero levanté la llamada de inspect.getmembers() desde su código. – jeremiahbuddha

+0

@jeremiahbuddha ¿Puede aceptar la respuesta o escribir la suya y aceptarla? –

Cuestiones relacionadas