unittest unit test skipif run modules examples espaƱol python unit-testing testing

unit - Prueba de unidad Python con base y clase secundaria



unittest python 3 (12)

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()

El resultado 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 volver a escribir lo anterior para que no se testCommon primer testCommon ?

EDITAR: en lugar de ejecutar 5 pruebas arriba, 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í mismo y necesito un mecanismo para evitar que eso suceda.


¿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 un prefijo de test por lo que unittest no los cargará.

import unittest class CommonTests(unittest.TestCase): def common_assertion(self, foo, bar, baz): # whatever common code self.assertEqual(foo(bar), baz) class BaseTest(CommonTests): def testCommon(self): print ''Calling BaseTest:testCommon'' value = 5 self.assertEquals(value, 5) class SubTest1(CommonTests): def testSub1(self): print ''Calling SubTest1:testSub1'' sub = 3 self.assertEquals(sub, 3) class SubTest2(CommonTests): def testSub2(self): print ''Calling SubTest2:testSub2'' sub = 4 self.assertEquals(sub, 4) if __name__ == ''__main__'': unittest.main()


Así que este es un hilo viejo, pero me encontré con este problema hoy y pensé en mi propio truco. Utiliza un decorador que realiza los valores de las funciones 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.

import types import unittest class FunctionValueOverride(object): def __init__(self, cls, default, override=None): self.cls = cls self.default = default self.override = override def __get__(self, obj, klass): if klass == self.cls: return self.override else: if obj: return types.MethodType(self.default, obj) else: return self.default def fixture(cls): for t in vars(cls): if not callable(getattr(cls, t)) or t[:4] != "test": continue setattr(cls, t, FunctionValueOverride(cls, getattr(cls, t))) return cls @fixture class BaseTest(unittest.TestCase): def testCommon(self): print(''Calling BaseTest:testCommon'') value = 5 self.assertEqual(value, 5) class SubTest1(BaseTest): def testSub1(self): print(''Calling SubTest1:testSub1'') sub = 3 self.assertEqual(sub, 3) class SubTest2(BaseTest): def testSub2(self): print(''Calling SubTest2:testSub2'') sub = 4 self.assertEqual(sub, 4) if __name__ == ''__main__'': unittest.main()


Cambie el nombre del método BaseTest para setUp:

class BaseTest(unittest.TestCase): def setUp(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)

Salida:

Ran 2 pruebas en 0.000s

Llamar a BaseTest: testCommon Calling
SubTest1: testSub1 Llamando
Prueba base: testCommon Calling
SubTest2: testSub2

De la documentation :

TestCase.setUp ()
Método llamado para preparar el dispositivo de prueba. Esto se llama inmediatamente antes de llamar al método de prueba; cualquier excepción planteada por este método se considerará un error en lugar de una falla de prueba. La implementación predeterminada no hace nada.


Hice casi lo mismo que @Vladim P. ( https://.com/a/25695512/2451329 ) pero ligeramente modificado:

import unittest2 from some_module import func1, func2 def make_base_class(func): class Base(unittest2.TestCase): def test_common1(self): print("in test_common1") self.assertTrue(func()) def test_common2(self): print("in test_common1") self.assertFalse(func(42)) return Base class A(make_base_class(func1)): pass class B(make_base_class(func2)): def test_func2_with_no_arg_return_bar(self): self.assertEqual("bar", func2())

y ahí vamos


La respuesta de Matthew Marshall es excelente, pero requiere que heredes de dos clases en cada uno de tus casos de prueba, que es propensa a errores. En cambio, uso esto (python> = 2.7):

class BaseTest(unittest.TestCase): @classmethod def setUpClass(cls): if cls is BaseTest: raise unittest.SkipTest("Skip BaseTest tests, it''s a base class") super(BaseTest, cls).setUpClass()


La respuesta de Matthew es la que necesitaba usar ya que estoy en 2.5 todavía. Pero a partir de 2.7 puede usar el decorador @ unittest.skip () en cualquier método de prueba que quiera omitir.

http://docs.python.org/library/unittest.html#skipping-tests-and-expected-failures

Tendrá que implementar su propio decorador de saltos para verificar el tipo de base. No he usado esta característica antes, pero en la parte superior de mi cabeza puedes usar BaseTest como un tipo de marcador para condicionar el salto:

def skipBaseTest(obj): if type(obj) is BaseTest: return unittest.skip("BaseTest tests skipped") return lambda func: func


No uses herencia múltiple, te morderá más later .

En su lugar, puede mover su clase base al módulo separado o envolverlo con la clase en blanco:

import unittest class BaseTestCases: class BaseTest(unittest.TestCase): def testCommon(self): print ''Calling BaseTest:testCommon'' value = 5 self.assertEquals(value, 5) class SubTest1(BaseTestCases.BaseTest): def testSub1(self): print ''Calling SubTest1:testSub1'' sub = 3 self.assertEquals(sub, 3) class SubTest2(BaseTestCases.BaseTest): def testSub2(self): print ''Calling SubTest2:testSub2'' sub = 4 self.assertEquals(sub, 4) if __name__ == ''__main__'': unittest.main()

La salida:

Calling BaseTest:testCommon .Calling SubTest1:testSub1 .Calling BaseTest:testCommon .Calling SubTest2:testSub2 . ---------------------------------------------------------------------- Ran 4 tests in 0.001s OK


Otra opción es no ejecutar

unittest.main()

En lugar de eso puedes usar

suite = unittest.TestLoader().loadTestsFromTestCase(TestClass) unittest.TextTestRunner(verbosity=2).run(suite)

Entonces solo ejecutas las pruebas en la clase TestClass


Puede resolver este problema con un solo comando:

del(BaseTest)

Entonces el código se vería así:

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) del(BaseTest) if __name__ == ''__main__'': unittest.main()


Simplemente cambie el nombre del método testCommon a otra cosa. Unittest (por lo general) se salta todo lo que no tenga ''test'' en él.

Rápido y simple

import unittest class BaseTest(unittest.TestCase): def methodCommon(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()`


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 saltan, por lo que los resultados de las pruebas pueden ser de color verde en lugar de amarillo en muchas herramientas de informes de pruebas.

Comparado con el método Mixin, ide como PyCharm no se quejará de que faltan métodos de prueba de la clase base.

Si una clase base hereda de esta clase, deberá anular los métodos setUpClass y tearDownClass .

class BaseTest(unittest.TestCase): @classmethod def setUpClass(cls): cls._test_methods = [] if cls is BaseTest: for name in dir(cls): if name.startswith(''test'') and callable(getattr(cls, name)): cls._test_methods.append((name, getattr(cls, name))) setattr(cls, name, lambda self: None) @classmethod def tearDownClass(cls): if cls is BaseTest: for name, method in cls._test_methods: setattr(cls, name, method) cls._test_methods = []


Usa la herencia múltiple, por lo que tu clase con pruebas comunes no hereda de TestCase.

import unittest class CommonTests(object): def testCommon(self): print ''Calling BaseTest:testCommon'' value = 5 self.assertEquals(value, 5) class SubTest1(unittest.TestCase, CommonTests): def testSub1(self): print ''Calling SubTest1:testSub1'' sub = 3 self.assertEquals(sub, 3) class SubTest2(unittest.TestCase, CommonTests): def testSub2(self): print ''Calling SubTest2:testSub2'' sub = 4 self.assertEquals(sub, 4) if __name__ == ''__main__'': unittest.main()