Pregunta

Les extiendo la pitón marco 2.7 unittest a hacer algunas pruebas de función. Una de las cosas que me gustaría hacer es detener todas las pruebas que se ejecute en el interior de una prueba, y en el interior de un método setUpClass(). A veces, si no pasa la prueba, el programa está tan roto que ya no sirve para nada es mantener la prueba, por lo que quiero para detener las pruebas de funcionamiento.

Me di cuenta de que un TestResult tiene un atributo shouldStop, y un método stop(), pero no estoy seguro de cómo obtener acceso a que en el interior de una prueba.

¿Alguien tiene alguna idea? ¿Hay una mejor manera?

¿Fue útil?

Solución 2

Aquí hay otra respuesta que se me ocurrió después de un tiempo:

En primer lugar, he añadido una nueva excepción:

class StopTests(Exception):
"""
Raise this exception in a test to stop the test run.

"""
    pass

Luego añadió un nuevo assert a mi clase de prueba hijo:

def assertStopTestsIfFalse(self, statement, reason=''):
    try:
        assert statement            
    except AssertionError:
        result.addFailure(self, sys.exc_info())

y por último me overrode la función run para incluir este derecho debajo de la llamada testMethod():

except StopTests:
    result.addFailure(self, sys.exc_info())
    result.stop()

Me gusta este mejor desde cualquier prueba ahora tiene la capacidad de detener todas las pruebas, y no hay ningún código CPython específica.

Otros consejos

En caso de estar interesado, aquí es un ejemplo sencillo de cómo se podría tomar una decisión acerca de sí mismo salir de un banco de pruebas limpiamente con py.test :

# content of test_module.py
import pytest
counter = 0
def setup_function(func):
    global counter
    counter += 1
    if counter >=3:
        pytest.exit("decided to stop the test run")

def test_one():
    pass
def test_two():
    pass
def test_three():
    pass

y si ejecuta este que se obtiene:

$ pytest test_module.py 
============== test session starts =================
platform linux2 -- Python 2.6.5 -- pytest-1.4.0a1
test path 1: test_module.py

test_module.py ..

!!!! Exit: decided to stop the test run !!!!!!!!!!!!
============= 2 passed in 0.08 seconds =============

También se puede poner la llamada py.test.exit() el interior de una prueba o en un plugin específico del proyecto.

Nota al margen: py.test soportes de forma nativa py.test --maxfail=NUM para implementar parar después de fracasos NUM

.

Sidenote2:. py.test tiene soporte únicamente limitada para la realización de pruebas en el estilo tradicional unittest.TestCase

En la actualidad, sólo se puede detener las pruebas a nivel privado. Una vez que esté en un TestCase, el método para la stop() TestResult no se utiliza cuando iteración a través de las pruebas.

Algo relacionado con su pregunta, si está utilizando Python 2.7, puede utilizar la bandera -f/--failfast cuando se llama a su prueba con python -m unittest. Esto detendrá la prueba en el primer fallo.

25.3.2.1. recuperación rápida, captura y buffer de comando opciones de línea de

También puede considerar el uso de nariz para ejecutar las pruebas y el uso de la -x, --stop bandera para detener la prueba temprana.

En el bucle de prueba de unittest.TestSuite, hay una condición break al inicio:

class TestSuite(BaseTestSuite):

    def run(self, result, debug=False):
        topLevel = False
        if getattr(result, '_testRunEntered', False) is False:
            result._testRunEntered = topLevel = True

        for test in self:
            if result.shouldStop:
                break

Así que estoy usando un conjunto de pruebas a medida como esta:

class CustomTestSuite(unittest.TestSuite):
    """ This variant registers the test result object with all ScriptedTests,
        so that a failed Loign test can abort the test suite by setting result.shouldStop
        to True
    """
    def run(self, result, debug=False):
        for test in self._tests:
            test.result = result

        return super(CustomTestSuite, self).run(result, debug)

con una clase personalizada resultado de la prueba como esta:

class CustomTestResult(TextTestResult):
    def __init__(self, stream, descriptions, verbosity):
        super(CustomTestResult, self).__init__(stream, descriptions, verbosity)
        self.verbosity = verbosity
        self.shouldStop = False

y mis clases de prueba son como:

class ScriptedTest(unittest.TestCase):
    def __init__(self, environment, test_cfg, module, test):
        super(ScriptedTest, self).__init__()
        self.result = None

Bajo ciertas condiciones, que luego abortar el conjunto de pruebas; por ejemplo, el conjunto de pruebas comienza con un inicio de sesión, y si eso no funciona, que no tienen que probar el resto:

    try:
        test_case.execute_script(test_command_list)
    except AssertionError as e:
        if test_case.module == 'session' and test_case.test == 'Login':
            test_case.result.shouldStop = True
            raise TestFatal('Login failed, aborting test.')
        else:
            raise sys.exc_info()

A continuación, utilizo el conjunto de pruebas de la siguiente manera:

    suite = CustomTestSuite()

    self.add_tests(suite)

    result = unittest.TextTestRunner(verbosity=self.environment.verbosity, stream=UnitTestLoggerStream(self.logger),
                                     resultclass=CustomTestResult).run(suite)

No estoy seguro de si hay una mejor manera de hacerlo, pero se comporta correctamente para mis pruebas.

Me miró a la clase TestCase y decidió hacerla una subclase. La clase sólo anula run(). He copiado el método y a partir de la línea 318 en la clase original añadido este:

# this is CPython specific. Jython and IronPython may do this differently
if testMethod.func_code.co_argcount == 2:
    testMethod(result)
else:
    testMethod()

Tiene algún código específico CPython allí para saber si el método de ensayo puede aceptar otro parámetro, pero ya que estoy usando CPython todas partes, esto no es un problema para mí.

A pesar de que no recibirá los informes de las pruebas habituales de las pruebas se ejecutan hasta el momento, de una manera muy fácil de detener la marcha de prueba desde dentro de un método TestCase es simplemente KeyboardInterrupt aumento dentro del método.

Se puede ver cómo única KeyboardInterrupt se le permite propagarse por corredor de prueba de unittest interior de mirar el código de CPython aquí testPartExecutor() interior.

Uso:

if condition: 
   return 'pass'
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top