Actualmente tengo algunas pruebas unitarias que comparten un conjunto común de pruebas. Aquí hay un ejemplo:
import unittest
class BaseTest(unittest.TestCase):
def testCommon(self):
print 'Calling BaseTest:testCommon'
value = 5
self.assertEquals(value, 5)
class SubTest1(BaseTest):
def testSub1(self):
print 'Calling SubTest1:testSub1'
sub = 3
self.assertEquals(sub, 3)
class SubTest2(BaseTest):
def testSub2(self):
print 'Calling SubTest2:testSub2'
sub = 4
self.assertEquals(sub, 4)
if __name__ == '__main__':
unittest.main()
La salida de lo anterior es:
Calling BaseTest:testCommon
.Calling BaseTest:testCommon
.Calling SubTest1:testSub1
.Calling BaseTest:testCommon
.Calling SubTest2:testSub2
.
----------------------------------------------------------------------
Ran 5 tests in 0.000s
OK
¿Hay alguna manera de reescribir lo anterior para que testCommon
no se llame al primero ?
EDITAR: en lugar de ejecutar 5 pruebas anteriores, quiero que ejecute solo 4 pruebas, 2 de SubTest1 y otras 2 de SubTest2. Parece que Python unittest está ejecutando el BaseTest original por sí solo y necesito un mecanismo para evitar que eso suceda.
python
unit-testing
testing
Thierry Lam
fuente
fuente
Respuestas:
Utilice la herencia múltiple, por lo que su clase con pruebas comunes no hereda de TestCase.
fuente
setUp
ytearDown
métodos a laCommonTests
clase, y desea que se los llame para cada prueba en clases derivadas, debe invertir el orden de las clases base, por lo que será:class SubTest1(CommonTests, unittest.TestCase)
.unittest.TestCase
yCommonTests
. Creo que elsetUpClass
siguiente método es el mejor y es menos propenso a errores humanos. O eso, o envolver la clase BaseTest en una clase contenedor que es un poco más hacky pero evita el mensaje de omisión en la impresión de ejecución de prueba.CommonTests
invoca métodos que no existen en esa clase.No uses herencia múltiple, te morderá más tarde .
En cambio, puede mover su clase base al módulo separado o envolverla con la clase en blanco:
La salida:
fuente
Puede resolver este problema con un solo comando:
Entonces el código se vería así:
fuente
self.assert*
métodos no existen en un objeto estándar.super( BaseTest, cls ).setUpClass( )
BaseTest
puede hacer referencia a través desuper(self.__class__, self)
o solosuper()
en las subclases, aunque aparentemente no si heredara constructores . Tal vez también existe una alternativa "anónima" cuando la clase base necesita referenciarse a sí misma (no es que tenga idea de cuándo una clase necesita referenciarse a sí misma).La respuesta de Matthew Marshall es excelente, pero requiere que heredes de dos clases en cada uno de tus casos de prueba, lo cual es propenso a errores. En cambio, uso esto (python> = 2.7):
fuente
¿Qué estás intentando lograr? Si tiene un código de prueba común (aserciones, pruebas de plantilla, etc.), colóquelos en métodos que no tengan el prefijo
test
paraunittest
que no los cargue.fuente
La respuesta de Matthew es la que necesitaba usar ya que todavía estoy en 2.5. Pero a partir de 2.7 puede usar el decorador @ unittest.skip () en cualquier método de prueba que desee omitir.
http://docs.python.org/library/unittest.html#skipping-tests-and-expected-failures
Tendrá que implementar su propio decorador de omisión para verificar el tipo base. No he usado esta función antes, pero desde la parte superior de mi cabeza puedes usar BaseTest como un tipo de marcador para condicionar el salto:
fuente
Una forma en que he pensado en resolver esto es ocultando los métodos de prueba si se usa la clase base. De esta forma, las pruebas no se omiten, por lo que los resultados pueden ser verdes en lugar de amarillos en muchas herramientas de informes de pruebas.
En comparación con el método mixin, ide's como PyCharm no se quejará de que faltan métodos de prueba unitaria en la clase base.
Si una clase base hereda de esta clase, deberá anular los métodos
setUpClass
ytearDownClass
.fuente
Puede agregar la
__test_ = False
clase BaseTest, pero si la agrega, tenga en cuenta que debe agregar las__test__ = True
clases derivadas para poder ejecutar las pruebas.fuente
Otra opción es no ejecutar
En lugar de eso puedes usar
Entonces solo ejecutas las pruebas en la clase
TestClass
fuente
unittest.main()
acumula en el conjunto predeterminado, forma un conjunto explícito y ejecuta sus pruebas.Hice casi lo mismo que @Vladim P. ( https://stackoverflow.com/a/25695512/2451329 ) pero ligeramente modificado:
y ahí vamos
fuente
A partir de Python 3.2, puede agregar una función test_loader a un módulo para controlar qué pruebas (si las hay) encuentra el mecanismo de descubrimiento de pruebas.
Por ejemplo, lo siguiente solo cargará los carteles originales
SubTest1
ySubTest2
los casos de prueba, ignorandoBase
:Debería ser posible realizar una iteración
standard_tests
(queTestSuite
contiene las pruebas que encontró el cargador predeterminado) y copiar todo, peroBase
en susuite
lugar, pero la naturaleza anidadaTestSuite.__iter__
hace que sea mucho más complicado.fuente
Simplemente cambie el nombre del método testCommon a otra cosa. Unittest (por lo general) omite cualquier cosa que no tenga "prueba".
Rápido y sencillo
fuente
Así que este es un hilo viejo, pero hoy me encontré con este problema y pensé en mi propio truco. Utiliza un decorador que convierte los valores de las funciones en Ninguno cuando se accede a través de la clase base. No necesita preocuparse por la configuración y la clase de configuración porque si la clase base no tiene pruebas, no se ejecutarán.
fuente
Aquí hay una solución que usa solo características documentadas de unittest y evita tener un estado de "omisión" en los resultados de la prueba:
Cómo funciona: según la
unittest.TestCase
documentación , "Cada instancia de TestCase ejecutará un único método base: el método llamado methodName". El "runTests" predeterminado ejecuta todos los métodos de prueba * en la clase, así es como funcionan normalmente las instancias de TestCase. Pero cuando se ejecuta en la propia clase base abstracta, simplemente puede anular ese comportamiento con un método que no hace nada.Un efecto secundario es que su recuento de pruebas aumentará en uno: la "prueba" runNoTestsInBaseClass se cuenta como una prueba exitosa cuando se ejecuta en BaseClass.
(Esto también funciona en Python 2.7, si todavía está en eso. Simplemente cambie
super()
asuper(BaseTest, self)
).fuente
Cambie el nombre del método BaseTest para configurar:
Salida:
De la documentación :
fuente
setUp
?test...
método,setUp
se ejecuta una y otra vez, una vez por cada método; ¡así que NO es una buena idea poner pruebas allí!