2010-03-28 15 views
7

Tengo problemas para organizar mi prueba de clase basada en unittest para la familia de pruebas. Por ejemplo, asuma que implemento una interfaz de "diccionario" y que quiero probar en 5 implementaciones diferentes.reutilización de pruebas unitarias para la familia de clases

Escribo una clase de prueba que prueba una interfaz de diccionario. ¿Pero cómo puedo reutilizarlo bien para probar todas mis clases? Hasta ahora yo fea:

DictType = hashtable.HashDict 

En la parte superior de archivo y luego usar DictType en la clase de prueba. Para probar otra clase, cambio manualmente el DictType a otra cosa.

¿Cómo puede hacer esto de otra manera? No se pueden pasar argumentos a las clases unittest, ¿hay alguna manera más agradable?

Respuesta

5

La forma en que lo abordo con la norma unittest es mediante subclases; la anulación de datos es tan fácil como los métodos generales, después de todo.

lo tanto, tengo una clase base para las pruebas:

class MappingTestBase(unittest.TestCase): 
    dictype = None 
    # write all the tests using self.dictype 

y subclases:

class HashtableTest(MappingTestBase): 
    dictype = hashtable.HashDict 

class OtherMappingTest(MappingTestBase): 
    dictype = othermodule.mappingimpl 

Aquí, las subclases sólo necesitan dictype anulan. A veces es más práctico también exponer MappingTestBase utilizar "métodos de gancho". Cuando los tipos que se prueban no tienen interfaces exactamente idénticas en todos los casos, esto puede solucionarse haciendo que las subclases anulen los métodos de enganche según sea necesario; este es el patrón de diseño "Método de plantilla", ver p. this page que tiene una colección comentada y cronológica de un par de videoconferencias sobre patrones de diseño. La parte II trata sobre el Método de plantilla y sus variantes durante aproximadamente los primeros 30 minutos.

No tiene que tener todo esto en un solo módulo, por supuesto (aunque a menudo me parece más claro exponerlo de esta manera, también podría hacer un módulo de prueba por cada tipo que esté probando, cada import ing el módulo con la clase base abstracta).

+0

oh, muy bonito, 10x alex – zaharpopov

+0

Estoy tratando de usar este patrón pero estoy obteniendo errores (p. ej., 'TypeError: 'NoneType' object no se puede llamar) porque el marco' unittest' ejecuta las pruebas dentro del contexto de 'MappingTestBase', así como las clases derivadas. ¿Hay alguna manera de evitar que esto suceda? ? – user200783

+0

@PaulBaker, sin duda, puede construir el conjunto de pruebas que desea ejecutar de manera muy explícita, por ejemplo, mediante el uso de la clase 'TestLoader', consulte https://docs.python.org/2/library/unittest.html#unittest.TestLoader , por ejemplo, subclassing y reemplazando 'getTestCaseNames' para devolver' [] 'para las clases cuyos métodos de prueba no desea ejecutar. O bien, puede decorar todos los métodos de prueba para simplemente devolver si' self.dicttype es None'. los enfoques funcionan bien. –

0

Puede consultar testscenarios que le permite establecer una lista llamada escenarios. Después, el código genera una versión de la clase de prueba para cada valor/escenario en la lista

Ver the example

Así que en su caso los escenarios serían una lista como [{dicttype: hashtable.HashDict}, {dicttype : otherimpl.class},] y usa self.dicttype en tu código de prueba.

+0

oh, entonces esto no es posible con solo la prueba unit? muy desalentador :-( – zaharpopov

+0

Todavía no - ver http://www.voidspace.org.uk/python/articles/unittest2.shtml para lo que se está haciendo – Mark

Cuestiones relacionadas