2011-03-17 5 views
7

De la documentación de Python (http://docs.python.org/library/unittest.html):parámetros en TestCase de la Suite en Python

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í es decir, cómo invocar a los caso_prueba:

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

¿es posible insertar 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 

?

+0

creo que u tiene que usar 'setattr' –

+0

¿Por qué haces esto? –

+0

custom_parameter contiene la dirección www para probar. Puedo escribir otra prueba unitaria para cada sitio que tengo que probar, pero sería una duplicación de código. – user278618

Respuesta

5

Lo que he hecho es en test_suite módulo se agregó

WidgetTestCase.CustomParameter="some_address" 

Las soluciones más simples son los mejores :)

0

No creo que sea así, la firma de setUp debe ser lo que unittest espera, afaik, setUp se llama automágicamente dentro del método de ejecución del testcase como setUp() ... no podrá pásalo a menos que anules la ejecución para pasar la var que deseas. Pero creo que lo que quiere derrota el propósito de la prueba de la unidad. 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.

3

Esto es algo que he tenido en mente recientemente. Sí, es muy posible hacerlo. Lo llamé scenario testing, pero creo que la parametrización puede ser más precisa. Puse una prueba de concepto como una esencia here. En resumen, es una metaclase que le permite definir un escenario y ejecutar las pruebas en su contra un montón. Con él su ejemplo puede ser algo como esto:

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 clase meta escribe 2 pruebas separadas a cabo 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 tests in 0.001s 

OK 

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

Ahora todavía no estoy seguro de si esto es una buena idea. Lo uso en pruebas donde tengo una gran cantidad de casos centrados en texto que repiten las mismas afirmaciones en datos ligeramente diferentes, lo que me ayuda a atrapar los pequeños casos extremos. Pero las clases en esa esencia funcionan y creo que logra lo que buscas.

Tenga en cuenta que con algunos trucos, los casos de prueba pueden recibir nombres e incluso extraerse de una fuente externa, como un archivo de texto o una base de datos. Aún no está documentado, pero algunos de los que están hurgando en la clase meta deberían ayudarte a empezar. También hay más información y ejemplos en mi publicación here.

Editar

Este es un truco feo que yo no apoyo más. La implementación debería haberse hecho como una subclase de TestCase, no como una metaclase pirateada. Vive y aprende. Una solución aún mejor sería usar nose generators.

3

He encontrado la manera de hacer esto, pero es un poco difícil.

Básicamente, lo que hago es añadir, a la TestCase, un método __init__ que define un parámetro 'default' y una __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(), I iterar sobre mis parámetros de prueba, sustituyendo el parámetro por defecto con 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 ser parametrizado.

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

0

No creo que sea una buena idea. Las pruebas unitarias deben ser lo suficientemente minuciosas para que pruebe todas las funciones en sus cajas, por lo que no debería exigir el paso de diferentes parámetros.

Menciona que pasa en una dirección de www; esta no es una buena idea. ¿Qué sucede si intenta ejecutar las pruebas en una máquina donde la conexión de red está inactiva? Sus pruebas deben ser:

  • automático - que se ejecutará en todas las máquinas y las plataformas en las que se apoya su aplicación, la intervención del usuario y sin . No deben confiar en que el entorno externo pase. Esto significa (entre otras cosas) que confiar en una conexión establecida correctamente a Internet es una mala idea. Puede evitar 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 el tipado 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).

  • Detallado: 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 tu aplicación, no puedo ofrecer muchos consejos en este punto.

Ahora, parece que sus pruebas van a estar basadas en gran medida en datos. Hay muchas herramientas que le permiten definir conjuntos de datos para pruebas unitarias y cargarlos en las pruebas. Mira los accesorios de prueba de Python, por ejemplo.

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

+0

. Solo porque estamos usando el marco 'unittest', no necesariamente significa que estamos haciendo pruebas unitarias. También se puede usar para hacer pruebas de regresión también. –

+0

En mi caso, para obtener una cobertura de código completa, necesitaba una docena de archivos de entrada, que cubrían diferentes casos de uso. Necesitaba probar media docena de funciones en cada una, así que en lugar de escribir 72 pruebas diferentes, escribí una sola clase TestCase con pruebas para cada una de las 6 funciones y la agregué al conjunto de pruebas varias veces, una para cada uno de los archivos de prueba. usando un diccionario para almacenar los resultados esperados. Resultó en un código de prueba más simple y limpio que era menos propenso a errores. –

+0

No es necesario escribir varias pruebas para diferentes datos de entrada. Eso obviamente sería ridículo. En tu pregunta, nunca mencionaste que no estás escribiendo pruebas unitarias, así que creo que es válido suponer que si estás usando la biblioteca unittest estarías ... ya sabes ... pruebas de unidades de escritura. – Thomi

Cuestiones relacionadas