Si realmente quiere tener multiplettest, entonces necesita múltiples métodos. La única forma de conseguirlo es a través de algún tipo de generación de código. Puede hacerlo a través de una metaclases, o ajustando la clase después de la definición, incluso (si usa Python 2.6) a través de un decorador de clases.
Aquí es una solución que busca el 'multitest' especial y los miembros '' multitest_values y utiliza los para construir los métodos de ensayo sobre la marcha. No es elegante, pero lo hace más o menos lo que quiere:
import unittest
import inspect
class SomeValue(object):
def __eq__(self, other):
return other in [1, 3, 4]
class ExampleTestCase(unittest.TestCase):
somevalue = SomeValue()
multitest_values = [1, 2, 3, 4]
def multitest(self, n):
self.assertEqual(self.somevalue, n)
multitest_gt_values = "ABCDEF"
def multitest_gt(self, c):
self.assertTrue(c > "B", c)
def add_test_cases(cls):
values = {}
functions = {}
# Find all the 'multitest*' functions and
# matching list of test values.
for key, value in inspect.getmembers(cls):
if key.startswith("multitest"):
if key.endswith("_values"):
values[key[:-7]] = value
else:
functions[key] = value
# Put them together to make a list of new test functions.
# One test function for each value
for key in functions:
if key in values:
function = functions[key]
for i, value in enumerate(values[key]):
def test_function(self, function=function, value=value):
function(self, value)
name ="test%s_%d" % (key[9:], i+1)
test_function.__name__ = name
setattr(cls, name, test_function)
add_test_cases(ExampleTestCase)
if __name__ == "__main__":
unittest.main()
Ésta es la salida de al ejecutarlo
% python stackoverflow.py
.F..FF....
======================================================================
FAIL: test_2 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 13, in multitest
self.assertEqual(self.somevalue, n)
AssertionError: <__main__.SomeValue object at 0xd9870> != 2
======================================================================
FAIL: test_gt_1 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 17, in multitest_gt
self.assertTrue(c > "B", c)
AssertionError: A
======================================================================
FAIL: test_gt_2 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 17, in multitest_gt
self.assertTrue(c > "B", c)
AssertionError: B
----------------------------------------------------------------------
Ran 10 tests in 0.001s
FAILED (failures=3)
Se puede ver de inmediato algunos de los problemas que se producen con la generación de código. ¿De dónde viene "test_gt_1"? Podría cambiar el nombre por el más largo "test_multitest_gt_1", pero ¿qué prueba es 1? Mejor aquí sería comenzar desde _0 en lugar de _1, y quizás en su caso sepa que los valores se pueden usar como nombre de función de Python.
No me gusta este enfoque. He trabajado en bases de código que autogeneraron los métodos de prueba (en un caso utilizando una metaclase) y descubrí que era mucho más difícil de entender que útil. Cuando una prueba fallaba, era difícil determinar el origen del caso de falla, y era difícil mantener el código de depuración para investigar el motivo de la falla.
(Las fallas de depuración en el ejemplo que escribí aquí no es tan difícil como el enfoque de metaclass específico con el que tuve que trabajar.)
¿Ha encontrado una manera de hacer esto? ¿O puede que hayas encontrado otra herramienta para esta tarea? Necesito tal comportamiento tampoco. – legesh
http://thebongtraveller.blogspot.sg/2015/12/art-of-unittest-writing-auto-generation.html ¿Es esto lo mismo? –