Dando parámetros a TestCase desde Suite en Python

De la documentación de python (http://docs.python.org/library/unittest.html):

import unittest class WidgetTestCase(unittest.TestCase): def setUp(self): self.widget = Widget('The widget') def tearDown(self): self.widget.dispose() self.widget = None def test_default_size(self): self.assertEqual(self.widget.size(), (50,50), 'incorrect default size') def test_resize(self): self.widget.resize(100,150) self.assertEqual(self.widget.size(), (100,150), 'wrong size after resize') 

Aquí está, cómo invocar esos testcase:

 def suite(): suite = unittest.TestSuite() suite.addTest(WidgetTestCase('test_default_size')) suite.addTest(WidgetTestCase('test_resize')) return suite 

¿Es posible insertar el parámetro custom_parameter en WidgetTestCase como:

 class WidgetTestCase(unittest.TestCase): def setUp(self,custom_parameter): self.widget = Widget('The widget') self.custom_parameter=custom_parameter 

?

    Lo que he hecho es en el módulo test_suite recién agregado

     WidgetTestCase.CustomParameter="some_address" 

    Las soluciones más simples son las mejores 🙂

    He encontrado una forma de hacer esto, pero es un poco un movimiento.

    Básicamente, lo que hago es agregar, al TestCase, un método __init__ que define un parámetro ‘predeterminado’ y un __str__ para que podamos distinguir los casos:

     class WidgetTestCase(unittest.TestCase): def __init__(self, methodName='runTest'): self.parameter = default_parameter unittest.TestCase.__init__(self, methodName) def __str__(self): ''' Override this so that we know which instance it is ''' return "%s(%s) (%s)" % (self._testMethodName, self.currentTest, unittest._strclass(self.__class__)) 

    Luego, en suite (), itero sobre mis parámetros de prueba, reemplazando el parámetro predeterminado por uno específico para cada prueba:

     def suite(): suite = unittest.TestSuite() for test_parameter in test_parameters: loadedtests = unittest.TestLoader().loadTestsFromTestCase(WidgetTestCase) for t in loadedtests: t.parameter = test_parameter suite.addTests(loadedtests) suite.addTests(unittest.TestLoader().loadTestsFromTestCase(OtherWidgetTestCases)) return suite 

    donde OtherWidgetTestCases son pruebas que no necesitan parametrización.

    Por ejemplo, tengo un montón de pruebas en datos reales para las cuales se debe aplicar un conjunto de pruebas a cada una, pero también tengo algunos conjuntos de datos sintéticos, diseñados para probar ciertos casos de borde que normalmente no están presentes en los datos, y solo necesito para aplicar ciertas pruebas a esas, para que obtengan sus propias pruebas en OtherWidgetTestCases .

    Esto es algo que he estado pensando recientemente. Sí, es muy posible hacerlo. Lo llamé prueba de escenarios , pero creo que parametrizado puede ser más preciso. Pongo aquí una prueba de concepto como una esencia. En resumen, es una meta clase que le permite definir un escenario y ejecutar las pruebas un montón. Con ello tu ejemplo puede ser algo así:

     class WidgetTestCase(unittest.TestCase): __metaclass__ = ScenarioMeta class widget_width(ScenerioTest): scenarios = [ dict(widget_in=Widget("One Way"), expected_tuple=(50, 50)), dict(widget_in=Widget("Another Way"), expected_tuple=(100, 150)) ] def __test__(self, widget_in, expected_tuple): self.assertEqual(widget_in.size, expected_tuple) 

    Cuando se ejecuta, la meta clase escribe 2 pruebas separadas por lo que la salida sería algo así como:

     $ python myscerariotest.py -v
     test_widget_width_0 (__main __. widget_width) ... ok
     test_widget_width_1 (__main __. widget_width) ... ok
    
    
     -------------------------------------------------- --------------------
     Ran 2 pruebas en 0.001s
    
     DE ACUERDO
    

    Como puede ver, los escenarios se convierten en pruebas en tiempo de ejecución.

    Ahora no estoy seguro si esto es una buena idea. Lo uso en pruebas en las que tengo muchos casos centrados en el texto que repiten las mismas afirmaciones en datos ligeramente diferentes, lo que me ayuda a detectar los casos de borde pequeño. Pero las clases en esa esencia funcionan y creo que logran lo que buscas.

    Tenga en cuenta que, con algunos trucos, a los casos de prueba se les pueden dar nombres e incluso se pueden extraer de una fuente externa, como un archivo de texto o una base de datos. Aún no está documentado, pero un poco de investigación en la meta clase debería ayudarlo a comenzar. También hay más información y ejemplos en mi publicación aquí .

    Editar

    Este es un truco feo que ya no apoyo. La implementación debería haberse realizado como una subclase de TestCase, no como una meta clase pirateada. Vive y aprende. Una solución aún mejor sería usar generadores de nariz .

    No lo creo, la firma para setUp debe ser lo que unittest espera, afaik, setUp se llama automáticamente en el método de ejecución del testcase como setUp () … no podrás pasarlo a menos que anula la ejecución para pasar la var que deseas. Pero creo que lo que quieres derrota el propósito de las pruebas unitarias . No intente usar una filosofía DRY con esto, cada unidad que está probando debe ser parte de una clase o incluso parte de una función / método.

    No creo que esta sea una buena idea. Las pruebas unitarias deben ser lo suficientemente exhaustivas como para probar toda la funcionalidad en sus casos, de modo que no se requiera pasar parámetros diferentes.

    Usted menciona que está pasando en una dirección www, esto no es una buena idea. ¿Qué sucede si intenta y ejecuta las pruebas en una máquina donde la conexión de red no funciona? Sus pruebas deben ser:

    • Automático: se ejecutarán en todas las máquinas y plataformas donde se admita su aplicación, sin la intervención del usuario. No deben confiar en el entorno externo para pasar. Esto significa (entre otras cosas) que confiar en una conexión correctamente configurada a Internet es una mala idea. Puede solucionar esto proporcionando datos ficticios. En lugar de pasar una URL a un recurso, abstraiga la fuente de datos y pase una secuencia de datos o lo que sea. Esto es especialmente fácil en Python, ya que puede utilizar la tipografía de pato de Python para presentar un objeto similar a una secuencia (python frecuentemente usa un objeto “similar a un archivo” por esta misma razón).

    • Completo: las pruebas de su unidad deben tener una cobertura de código del 100% y cubrir todas las situaciones posibles. ¿Quieres probar tu código con múltiples sitios? En su lugar, pruebe su código con todas las características posibles que un sitio puede incluir. Sin saber más sobre lo que hace su aplicación, no puedo ofrecerle muchos consejos en este punto.

    Ahora, parece que tus pruebas van a estar fuertemente basadas en datos. Existen muchas herramientas que le permiten definir conjuntos de datos para pruebas unitarias y cargarlos en las pruebas. Echa un vistazo a los accesorios de prueba de Python, por ejemplo.

    Me doy cuenta de que esta no es la respuesta que está buscando, pero creo que, a la larga, tendrá más alegría si sigue estos principios.