2010-11-30 17 views
9

Tengo varias clases que comparten algunas invariantes y tienen una interfaz común, y me gustaría ejecutar automáticamente la misma prueba para cada una de ellas.¿Cómo ejecutar el mismo caso de prueba para diferentes clases?

Como ejemplo, supongamos que tengo varias clases que implementan diferentes enfoques para particionar un conjunto de datos. La invariante común aquí sería que, para todas estas clases, la unión sobre todas las particiones debería ser igual al conjunto de datos original.

Lo que tengo actualmente es como la siguiente:

class PartitionerInvariantsTests(unittest.TestCase): 
    def setUp(self): 
     self.testDataSet = range(100) # create test-data-set 

    def impl(self, partitioner): 
     self.assertEqual(self.testDataSet, 
         chain.from_iterable(partitioner(self.testDataSet)) 

Luego añadir una función diferente que llama impl para cada una de las clases que quiero probar con una instancia de esa clase. El problema con esto se hace evidente al hacer esto para más de una función de prueba. Supongamos que tengo 5 funciones de prueba y 5 clases que quiero probar. Esto haría 25 funciones que parecen casi idénticas para invocar todas las pruebas.

Otro enfoque en el que estaba pensando era implementar la plantilla como una superclase, y luego crear una subclase para cada una de las clases que quiero probar. Las subclases podrían proporcionar una función para crear instancias de la clase. El problema con eso es que el cargador de prueba predeterminado consideraría la clase base (inutilizable) como un caso de prueba válido y trataría de ejecutarlo, lo cual fallaría.

¿Cuáles son sus sugerencias?

P.S .: Estoy usando Python 2.6

+1

¿Intenta ejecutar la clase base si no hereda de 'unittest.TestCase'? – nmichaels

+0

@Nathon: Ahora que lo dices, todavía no lo he intentado. –

+0

@Nathon, si desea publicar su idea como respuesta, con gusto eliminaré la mía. – unutbu

Respuesta

11

podría utilizar varios herencia.

class PartitionerInvariantsFixture(object): 
    def setUp(self): 
     self.testDataSet = range(100) # create test-data-set 
     super(PartitionInvariantsFixture, self).setUp() 

    def test_partitioner(self): 
     TestCase.assertEqual(self.testDataSet, 
        chain.from_iterable(self.partitioner(self.testDataSet)) 

class MyClassTests(TestCase, PartitionerInvariantsFixture): 
    partitioner = Partitioner 
+0

El iterador de cadena probablemente se iterará usando list (chain ...) – kevpie

+3

¿por qué necesitamos llamar a super en la configuración? – dylam

+0

+1 Mi mandíbula se cae. Hay docenas de preguntas similares en SO (ejecutando las mismas pruebas en diferentes objetos con core unittest), pero esta es definitivamente la mejor respuesta que he encontrado. Ni siquiera sabía (o no recordaba) que Python tenía herencia múltiple. –

0

Subclase PartitionerInvariantsTests:

class PartitionerInvariantsTests(unittest.TestCase): 
    def test_impl(self): 
     self.assertEqual(self.testDataSet, 
         chain.from_iterable(self.partitioner(self.testDataSet)) 

class PartitionerATests(PartitionerInvariantsTests): 

para cada clase de particionamiento que desea probar. Entonces se ejecutará test_impl para cada clase de Particionador, en virtud de la herencia.

Siguiendo con el comentario de Nathon, puede impedir que la clase base desde la que se está probando por tener que heredan sólo de object:

import unittest 

class Test(object): 
    def test_impl(self): 
     print('Hi') 

class TestA(Test,unittest.TestCase): 
    pass 

class TestB(Test,unittest.TestCase): 
    pass 

if __name__ == '__main__': 
    unittest.sys.argv.insert(1,'--verbose') 
    unittest.main(argv = unittest.sys.argv)  

Operando rendimientos test.py

test_impl (__main__.TestA) ... Hi 
ok 
test_impl (__main__.TestB) ... Hi 
ok 

---------------------------------------------------------------------- 
Ran 2 tests in 0.000s 

OK 
+2

Sí, pero la clase base también se ejecutará y fallará. ¿Hay alguna forma de ejecutar las subclases, pero no la clase base? –

Cuestiones relacionadas