2008-08-28 9 views
151

Tengo algún tipo de datos de prueba y deseo crear una prueba unitaria para cada elemento. Mi primera idea era hacerlo de esta manera:¿Cómo se generan pruebas de unidades dinámicas (parametrizadas) en python?

import unittest 

l = [["foo", "a", "a",], ["bar", "a", "b"], ["lee", "b", "b"]] 

class TestSequence(unittest.TestCase): 
    def testsample(self): 
     for name, a,b in l: 
      print "test", name 
      self.assertEqual(a,b) 

if __name__ == '__main__': 
    unittest.main() 

La desventaja de esto es que se encarga de todos los datos en una sola prueba. Me gustaría generar una prueba para cada artículo sobre la marcha. ¿Alguna sugerencia?

+0

posible duplicado de [unittest Python:? Generar múltiples pruebas de programación] (http://stackoverflow.com/questions/2798956/python-unittest-generate-multiple-tests- programáticamente) – Nakilon

+2

Un buen enlace que puede proporcionar una respuesta: http://eli.thegreenplace.net/2014/04/02/dynamically-generating-python-test-cases – gaborous

Respuesta

109

yo uso algo como esto:

import unittest 

l = [["foo", "a", "a",], ["bar", "a", "b"], ["lee", "b", "b"]] 

class TestSequense(unittest.TestCase): 
    pass 

def test_generator(a, b): 
    def test(self): 
     self.assertEqual(a,b) 
    return test 

if __name__ == '__main__': 
    for t in l: 
     test_name = 'test_%s' % t[0] 
     test = test_generator(t[1], t[2]) 
     setattr(TestSequense, test_name, test) 
    unittest.main() 

El paquete nose-parameterized se puede utilizar para automatizar este proceso:

from nose_parameterized import parameterized 

class TestSequence(unittest.TestCase): 
    @parameterized.expand([ 
     ["foo", "a", "a",], 
     ["bar", "a", "b"], 
     ["lee", "b", "b"], 
    ]) 
    def test_sequence(self, name, a, b): 
     self.assertEqual(a,b) 

que generará las pruebas:

test_sequence_0_foo (__main__.TestSequence) ... ok 
test_sequence_1_bar (__main__.TestSequence) ... FAIL 
test_sequence_2_lee (__main__.TestSequence) ... ok 

====================================================================== 
FAIL: test_sequence_1_bar (__main__.TestSequence) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/usr/local/lib/python2.7/site-packages/nose_parameterized/parameterized.py", line 233, in <lambda> 
    standalone_func = lambda *a: func(*(a + p.args), **p.kwargs) 
    File "x.py", line 12, in test_sequence 
    self.assertEqual(a,b) 
AssertionError: 'a' != 'b' 
+22

En realidad, bignose, este código NO genera un nombre diferente para cada prueba (en realidad no funcionaría de otra manera). En el ejemplo dado, las pruebas ejecutadas se denominarán "test_foo", "test_bar" y "test_lee", respectivamente. Por lo tanto, el beneficio que menciona (y es grande) se conserva siempre que genere nombres razonables. – Toji

+0

Como dice la respuesta de @codeape, nose maneja esto. Sin embargo, la nariz no parece manejar Unicode; por lo tanto, para mí esta es una solución preferible. +1 –

+0

Como dice la respuesta de @codeape a continuación, nose tiene soporte para esto. Sin embargo, no parece ser compatible con Unicode muy bien. Por lo tanto, este responable es preferible a aquellos que están ejecutando pruebas con datos Unicode. +1 –

59

El nose marco de prueba supports this.

Ejemplo (el código siguiente es el contenido completo del archivo que contiene la prueba):

param_list = [('a', 'a'), ('a', 'b'), ('b', 'b')] 

def test_generator(): 
    for params in param_list: 
     yield check_em, params[0], params[1] 

def check_em(a, b): 
    assert a == b 

La salida del comando nosetests:

> nosetests -v 
testgen.test_generator('a', 'a') ... ok 
testgen.test_generator('a', 'b') ... FAIL 
testgen.test_generator('b', 'b') ... ok 

====================================================================== 
FAIL: testgen.test_generator('a', 'b') 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/usr/lib/python2.5/site-packages/nose-0.10.1-py2.5.egg/nose/case.py", line 203, in runTest 
    self.test(*self.arg) 
    File "testgen.py", line 7, in check_em 
    assert a == b 
AssertionError 

---------------------------------------------------------------------- 
Ran 3 tests in 0.006s 

FAILED (failures=1) 
+2

Esa es una forma muy limpia de generar dinámicamente casos de prueba. – gaborous

+1

La mejor respuesta de lejos. Tan corto y tan limpio. – user1820801

+0

Pero tenga en cuenta que 'setup()' no sabrá qué variables se utilizan como argumentos para ceder. En realidad setup() no sabrá qué prueba se está ejecutando, o vars se estableció dentro de test_generator(). Esto complica la comprobación de la cordura dentro de setup(), y es una de las razones por las que algunas personas prefieren py.test. –

6

que se beneficiaría de tratar la biblioteca TestScenarios .

testscenarios provides clean dependency injection for python unittest style tests. This can be used for interface testing (testing many implementations via a single test suite) or for classic dependency injection (provide tests with dependencies externally to the test code itself, allowing easy testing in different situations).

51

Esto se puede resolver elegantemente usando metaclases:

import unittest 

l = [["foo", "a", "a",], ["bar", "a", "b"], ["lee", "b", "b"]] 

class TestSequenceMeta(type): 
    def __new__(mcs, name, bases, dict): 

     def gen_test(a, b): 
      def test(self): 
       self.assertEqual(a, b) 
      return test 

     for tname, a, b in l: 
      test_name = "test_%s" % tname 
      dict[test_name] = gen_test(a,b) 
     return type.__new__(mcs, name, bases, dict) 

class TestSequence(unittest.TestCase): 
    __metaclass__ = TestSequenceMeta 

if __name__ == '__main__': 
    unittest.main() 
+0

muy agradable, encontré varios problemas con setattr, ¡esto simplemente funciona! – OriginalCliche

+1

Esto funcionó EXCELENTE para mí con Selenium. Como nota, en la clase TestSequence, puede definir métodos "estáticos" como setUp (self), is_element_present (self, how, what), ... tearDown (self). Poniéndolos DESPUÉS de que la declaración "__metaclass__ = TestSequenceMeta" parece funcionar. –

+1

Esta solución es mejor que la seleccionada como mi humilde opinión. – petroslamb

27

load_tests es un poco de mecanismo conocido introducido en 2.7 para crear dinámicamente un TestSuite. Con él, puede crear fácilmente pruebas parametrizadas.

Por ejemplo:

import unittest 

class GeneralTestCase(unittest.TestCase): 
    def __init__(self, methodName, param1=None, param2=None): 
     super(GeneralTestCase, self).__init__(methodName) 

     self.param1 = param1 
     self.param2 = param2 

    def runTest(self): 
     pass # Test that depends on param 1 and 2. 


def load_tests(loader, tests, pattern): 
    test_cases = unittest.TestSuite() 
    for p1, p2 in [(1, 2), (3, 4)]: 
     test_cases.addTest(GeneralTestCase('runTest', p1, p2)) 
    return test_cases 

Ese código se ejecutará todos los casos que sienta jurisprudencia en la TestSuite devuelto por load_tests. El mecanismo de descubrimiento no ejecuta automáticamente otras pruebas.

Alternativamente, también puede utilizar la herencia, como se muestra en este billete: http://bugs.python.org/msg151444

+1

El código anterior falla: TypeError: __init __() toma como máximo 2 argumentos (4 proporcionados) – max

+1

Se agregaron valores predeterminados nulos a los parámetros adicionales del constructor. – Javier

+0

Prefiero el código de parámetro de la nariz en [respuesta de @ mojo] (http://stackoverflow.com/a/32939/527489), pero para mis clientes es demasiado útil para evitar una dependencia adicional, así que voy a usar esto para ellos. – sage

22

Se puede hacer mediante el uso de pytest. Sólo tiene que escribir el archivo con el contenido test_me.py:

import pytest 

@pytest.mark.parametrize('name, left, right', [['foo', 'a', 'a'], 
               ['bar', 'a', 'b'], 
               ['baz', 'b', 'b']]) 
def test_me(name, left, right): 
    assert left == right, name 

y ejecutar el comando de prueba con py.test --tb=short test_me.py. A continuación, la salida será el siguiente aspecto:

=========================== test session starts ============================ 
platform darwin -- Python 2.7.6 -- py-1.4.23 -- pytest-2.6.1 
collected 3 items 

test_me.py .F. 

================================= FAILURES ================================= 
_____________________________ test_me[bar-a-b] _____________________________ 
test_me.py:8: in test_me 
    assert left == right, name 
E AssertionError: bar 
==================== 1 failed, 2 passed in 0.01 seconds ==================== 

Es sencillo !. También pytest tiene más funciones, como fixtures, mark, assert, etc ...

+0

Estaba buscando un ejemplo simple y directo de cómo parametrizar casos de prueba con py.test. ¡Muchas gracias! – timgeb

+0

@timgeb Me alegra poder ayudarlo. Consulte la etiqueta [py.test] (http://stackoverflow.com/questions/tagged/py.test) para obtener más ejemplos. También sugiero usar [hamcrest] (https://github.com/hamcrest/PyHamcrest) para agregar algo de azúcar a sus afirmaciones con mutchers legibles por humanos, que pueden ser modificados, combinados o creados por su propia cuenta. Además, tenemos [allure-python] (https://github.com/allure-framework/allure-python), una agradable generación de informes para 'py.test' –

+0

Gracias. Acabo de empezar a pasar de 'unittest' a py.test. Solía ​​tener clases base 'TestCase' que podían crear dinámicamente niños con diferentes argumentos que almacenarían como variables de clase ... que era un poco difícil de manejar. – timgeb

4

Puede utilizar nose-ittr plug-in (pip install nose-ittr).

Es muy fácil de integrar con las pruebas existentes, se requieren cambios mínimos (si corresponde). También es compatible con nose plugin de multiprocesamiento.

No es que también pueda tener una función de personalizar setup por prueba.

@ittr(number=[1, 2, 3, 4]) 
def test_even(self): 
    assert_equal(self.number % 2, 0) 

También es posible pasar nosetest parámetros como con su acumulación en el plug-in attrib, de esta manera sólo se puede ejecutar una prueba específica con el parámetro específico:

nosetest -a number=2 
+0

Me gusta este enfoque, especialmente el nivel por método que admite. – Matt

2

me encontré con ParamUnittest la otra día cuando se mira el código fuente a radon (example usage on the github repo). Debería funcionar con otros frameworks que extienden TestCase (como Nose).

Aquí se muestra un ejemplo:

import unittest 
import paramunittest 


@paramunittest.parametrized(
    ('1', '2'), 
    #(4, 3), <---- uncomment to have a failing test 
    ('2', '3'), 
    (('4',), {'b': '5'}), 
    ((), {'a': 5, 'b': 6}), 
    {'a': 5, 'b': 6}, 
) 
class TestBar(TestCase): 
    def setParameters(self, a, b): 
     self.a = a 
     self.b = b 

    def testLess(self): 
     self.assertLess(self.a, self.b) 
36

A partir de Python 3.4 se han introducido subpruebas a unittest para este propósito. Ver the documentation para más detalles. TestCase.subTest es un gestor de contexto que permite aislar afirmaciones en una prueba para que una falla se informe con información de parámetros pero no detenga la ejecución de la prueba. Aquí está el ejemplo de la documentación:

class NumbersTest(unittest.TestCase): 

def test_even(self): 
    """ 
    Test that numbers between 0 and 5 are all even. 
    """ 
    for i in range(0, 6): 
     with self.subTest(i=i): 
      self.assertEqual(i % 2, 0) 

La salida de una prueba de funcionamiento sería:

====================================================================== 
FAIL: test_even (__main__.NumbersTest) (i=1) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "subtests.py", line 32, in test_even 
    self.assertEqual(i % 2, 0) 
AssertionError: 1 != 0 

====================================================================== 
FAIL: test_even (__main__.NumbersTest) (i=3) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "subtests.py", line 32, in test_even 
    self.assertEqual(i % 2, 0) 
AssertionError: 1 != 0 

====================================================================== 
FAIL: test_even (__main__.NumbersTest) (i=5) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "subtests.py", line 32, in test_even 
    self.assertEqual(i % 2, 0) 
AssertionError: 1 != 0 

Esto también es parte de unittest2, por lo que está disponible para las versiones anteriores de Python.

+1

La mejor solución si usa Python 3.4 y superior. –

+4

Usando unittest2, esto también está disponible para Python 2.7. – Bernhard

+8

Una diferencia importante entre este enfoque y tener pruebas separadas es que el estado de prueba no se restablece cada vez. (Es decir, 'setUp()' y 'tearDown()' no se ejecutan entre las pruebas secundarias). –

8

Utilice la biblioteca ddt. Se añade decoradores simples para los métodos de ensayo:

import unittest 
from ddt import ddt, data 
from mycode import larger_than_two 

@ddt 
class FooTestCase(unittest.TestCase): 

    @data(3, 4, 12, 23) 
    def test_larger_than_two(self, value): 
     self.assertTrue(larger_than_two(value)) 

    @data(1, -3, 2, 0) 
    def test_not_larger_than_two(self, value): 
     self.assertFalse(larger_than_two(value)) 

Esta biblioteca se puede instalar con pip. No requiere nose, y funciona de manera excelente con el módulo de biblioteca estándar unittest.

1

Solo use metaclases, como se ve aquí;

class DocTestMeta(type): 
    """ 
    Test functions are generated in metaclass due to the way some 
    test loaders work. For example, setupClass() won't get called 
    unless there are other existing test methods, and will also 
    prevent unit test loader logic being called before the test 
    methods have been defined. 
    """ 
    def __init__(self, name, bases, attrs): 
     super(DocTestMeta, self).__init__(name, bases, attrs) 

    def __new__(cls, name, bases, attrs): 
     def func(self): 
      """Inner test method goes here""" 
      self.assertTrue(1) 

     func.__name__ = 'test_sample' 
     attrs[func.__name__] = func 
     return super(DocTestMeta, cls).__new__(cls, name, bases, attrs) 

class ExampleTestCase(TestCase): 
    """Our example test case, with no methods defined""" 
    __metaclass__ = DocTestMeta 

Salida:

test_sample (ExampleTestCase) ... OK 
2

utilizo metaclases y decoradores para generar pruebas. Puede verificar mi implementación python_wrap_cases. Esta biblioteca no requiere ningún marco de prueba.

Su ejemplo:

import unittest 
from python_wrap_cases import wrap_case 


@wrap_case 
class TestSequence(unittest.TestCase): 

    @wrap_case("foo", "a", "a") 
    @wrap_case("bar", "a", "b") 
    @wrap_case("lee", "b", "b") 
    def testsample(self, name, a, b): 
     print "test", name 
     self.assertEqual(a, b) 

salida de la consola:

testsample_u'bar'_u'a'_u'b' (tests.example.test_stackoverflow.TestSequence) ... test bar 
FAIL 
testsample_u'foo'_u'a'_u'a' (tests.example.test_stackoverflow.TestSequence) ... test foo 
ok 
testsample_u'lee'_u'b'_u'b' (tests.example.test_stackoverflow.TestSequence) ... test lee 
ok 

También se puede utilizar generadores .Por ejemplo, este código de generar todas las combinaciones posibles de las pruebas con argumentos a__list y b__list

import unittest 
from python_wrap_cases import wrap_case 


@wrap_case 
class TestSequence(unittest.TestCase): 

    @wrap_case(a__list=["a", "b"], b__list=["a", "b"]) 
    def testsample(self, a, b): 
     self.assertEqual(a, b) 

salida de la consola:

1

Puede usar las clases TestSuite y TestCase personalizadas.

import unittest 

class CustomTest(unittest.TestCase): 
    def __init__(self, name, a, b): 
     super().__init__() 
     self.name = name 
     self.a = a 
     self.b = b 

    def runTest(self): 
     print("test", self.name) 
     self.assertEqual(self.a, self.b) 

if __name__ == '__main__': 
    suite = unittest.TestSuite() 
    suite.addTest(CustomTest("Foo", 1337, 1337)) 
    suite.addTest(CustomTest("Bar", 0xDEAD, 0xC0DE)) 
    unittest.TextTestRunner().run(suite) 
+0

Mientras TestSuite funciona, los argumentos no se pasan a la función '__init__'. – jadelord

0

He estado teniendo problemas con un estilo muy particular de pruebas parametrizadas. Todas nuestras pruebas de Selenium pueden ejecutarse localmente, pero también deben poder ejecutarse de forma remota contra varias plataformas en SauceLabs. Básicamente, quería tomar una gran cantidad de casos de prueba ya escritos y parametrizarlos con el menor número posible de cambios en el código. Además, necesitaba poder pasar los parámetros al método setUp, algo que no he visto ninguna solución para otro lado.

Aquí es lo que he llegado con:

import inspect 
import types 

test_platforms = [ 
    {'browserName': "internet explorer", 'platform': "Windows 7", 'version': "10.0"}, 
    {'browserName': "internet explorer", 'platform': "Windows 7", 'version': "11.0"}, 
    {'browserName': "firefox", 'platform': "Linux", 'version': "43.0"}, 
] 


def sauce_labs(): 
    def wrapper(cls): 
     return test_on_platforms(cls) 
    return wrapper 


def test_on_platforms(base_class): 
    for name, function in inspect.getmembers(base_class, inspect.isfunction): 
     if name.startswith('test_'): 
      for platform in test_platforms: 
       new_name = '_'.join(list([name, ''.join(platform['browserName'].title().split()), platform['version']])) 
       new_function = types.FunctionType(function.__code__, function.__globals__, new_name, 
                function.__defaults__, function.__closure__) 
       setattr(new_function, 'platform', platform) 
       setattr(base_class, new_name, new_function) 
      delattr(base_class, name) 

    return base_class 

Con esto, todo lo que tenía que hacer era añadir un simple @sauce_labs decorador() para cada edad TestCase regular, y ahora cuando se ejecuta ellos, Están envueltos y reescritos, de modo que todos los métodos de prueba se parametrizan y cambian de nombre. LoginTests.test_login (self) se ejecuta como LoginTests.test_login_internet_explorer_10.0 (self), LoginTests.test_login_internet_explorer_11.0 (self) y LoginTests.test_login_firefox_43.0 (self), y cada uno tiene el parámetro self.platform para decidir qué navegador/plataforma contra la cual ejecutar, incluso en LoginTests.setUp, que es crucial para mi tarea, ya que ahí es donde se inicia la conexión a SauceLabs.

De todos modos, ¡espero que esto pueda ser útil para alguien que quiera hacer una parametrización "global" similar de sus pruebas!

-1

Además de usar setattr, podemos usar load_test desde python 3.2. Consulte la publicación de blog blog.livreuro.com/en/coding/python/how-to-generate-discoverable-unit-tests-in-python-dynamically/

class Test(unittest.TestCase): 
    pass 

def _test(self, file_name): 
    open(file_name, 'r') as f: 
     self.assertEqual('test result',f.read()) 

def _generate_test(file_name): 
    def test(self): 
     _test(self, file_name) 
    return test 

def _generate_tests(): 
    for file in files: 
     file_name = os.path.splitext(os.path.basename(file))[0] 
     setattr(Test, 'test_%s' % file_name, _generate_test(file)) 

test_cases = (Test,) 

def load_tests(loader, tests, pattern): 
    _generate_tests() 
    suite = TestSuite() 
    for test_class in test_cases: 
     tests = loader.loadTestsFromTestCase(test_class) 
     suite.addTests(tests) 
    return suite 

if __name__ == '__main__': 
    _generate_tests() 
    unittest.main() 
-1

La siguiente es mi solución. Me resulta útil cuando: 1. Debería funcionar para unittest.Testcase y unittest discover 2. Haga que se ejecute un conjunto de pruebas para diferentes configuraciones de parámetros. 3.Muy simple sin dependencia de otros paquetes importación unittest

class BaseClass(unittest.TestCase): 
     def setUp(self): 
      self.param = 2 
      self.base = 2 

     def test_me(self): 
      self.assertGreaterEqual(5, self.param+self.base) 

     def test_me_too(self): 
      self.assertLessEqual(3, self.param+self.base) 



    class Child_One(BaseClass): 
     def setUp(self): 
      BaseClass.setUp(self) 
      self.param = 4 


    class Child_Two(BaseClass): 
     def setUp(self): 
      BaseClass.setUp(self) 
      self.param = 1 
+0

¿Por qué votar abajo? –

+0

Esto no responde la pregunta, que se trata de generar pruebas sobre la marcha. – lenz

0

Esta solución funciona con unittest y nose:

#!/usr/bin/env python 
import unittest 

def make_function(description, a, b): 
    def ghost(self): 
     self.assertEqual(a, b, description) 
    print description 
    ghost.__name__ = 'test_{0}'.format(description) 
    return ghost 


class TestsContainer(unittest.TestCase): 
    pass 

testsmap = { 
    'foo': [1, 1], 
    'bar': [1, 2], 
    'baz': [5, 5]} 

def generator(): 
    for name, params in testsmap.iteritems(): 
     test_func = make_function(name, params[0], params[1]) 
     setattr(TestsContainer, 'test_{0}'.format(name), test_func) 

generator() 

if __name__ == '__main__': 
    unittest.main() 
1
import unittest 

def generator(test_class, a, b): 
    def test(self): 
     self.assertEqual(a, b) 
    return test 

def add_test_methods(test_class): 
    #First element of list is variable "a", then variable "b", then name of test case that will be used as suffix. 
    test_list = [[2,3, 'one'], [5,5, 'two'], [0,0, 'three']] 
    for case in test_list: 
     test = generator(test_class, case[0], case[1]) 
     setattr(test_class, "test_%s" % case[2], test) 


class TestAuto(unittest.TestCase): 
    def setUp(self): 
     print 'Setup' 
     pass 

    def tearDown(self): 
     print 'TearDown' 
     pass 

_add_test_methods(TestAuto) # It's better to start with underscore so it is not detected as a test itself 

if __name__ == '__main__': 
    unittest.main(verbosity=1) 

resultado:

>>> 
Setup 
FTearDown 
Setup 
TearDown 
.Setup 
TearDown 
. 
====================================================================== 
FAIL: test_one (__main__.TestAuto) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "D:/inchowar/Desktop/PyTrash/test_auto_3.py", line 5, in test 
    self.assertEqual(a, b) 
AssertionError: 2 != 3 

---------------------------------------------------------------------- 
Ran 3 tests in 0.019s 

FAILED (failures=1) 
+0

Problema menor con la función 'def add_test_methods'. Debería ser 'def _add_test_methods' Creo – Raychaser

+0

@Raychaser ... Estás en lo correcto ... Lo arreglé pero no lo actualicé aquí ... Gracias por captar eso. –

0

Las respuestas basadas en MetaClass fijas trabajar en Python3, pero en lugar del __metaclass__ atributo que uno tiene que utilizar el parámetro metaclass, como en:

class ExampleTestCase(TestCase,metaclass=DocTestMeta): 
    pass 
0

Meta-programación es divertido, pero se puede conseguir en el camino. La mayoría de las soluciones aquí hacen que sea difícil:

  • lanzar selectivamente una prueba
  • punto de volver al nombre del código dado de prueba

lo tanto, mi primera sugerencia es seguir el camino simple/explícita (obras con cualquier corredor de prueba):

import unittest 

class TestSequence(unittest.TestCase): 

    def _test_complex_property(self, a, b): 
     self.assertEqual(a,b) 

    def test_foo(self): 
     self._test_complex_property("a", "a") 
    def test_bar(self): 
     self._test_complex_property("a", "b") 
    def test_lee(self): 
     self._test_complex_property("b", "b") 

if __name__ == '__main__': 
    unittest.main() 

Dado que no hay que repetir nosotros mismos, mi segunda sugerencia se basa en la respuesta de Javier @: abrazar las pruebas basadas en la propiedad. biblioteca hipótesis:

  • es "más implacablemente tortuosa acerca de la generación de casos de prueba que nosotros los simples humanos"
  • proporcionará simple recuento-ejemplos
  • funciona con cualquier corredor de prueba
  • tiene muchas más características interesantes (estadísticas, salida de prueba adicional, ...)

    clase TestSequence (unittest.TestCase):

    @given(st.text(), st.text()) 
    def test_complex_property(self, a, b): 
        self.assertEqual(a,b) 
    

Para probar sus ejemplos específicos, sólo tiene que añadir:

@example("a", "a") 
    @example("a", "b") 
    @example("b", "b") 

para ejecutarse sólo un ejemplo particular, se puede comentar los otros ejemplos (proporcionado ejemplo, se llevará a cabo en primer lugar). Es posible que desee utilizar @given(st.nothing()). Otra opción es reemplazar todo el bloque por:

@given(st.just("a"), st.just("b")) 

Ok, usted no tiene los nombres de pruebas distintas. Pero quizás solo necesite:

  • nombre descriptivo de la propiedad bajo prueba.
  • cuya entrada conduce a una falla (ejemplo de falsificación).

Funnier example

0

super tarde a la fiesta, pero no tenía problemas para hacer estos trabajos para setUpClass.

Aquí hay una versión de @Javier's answer que da acceso a setUpClass a los atributos asignados dinámicamente.

import unittest 


class GeneralTestCase(unittest.TestCase): 
    @classmethod 
    def setUpClass(cls): 
     print '' 
     print cls.p1 
     print cls.p2 

    def runTest1(self): 
     self.assertTrue((self.p2 - self.p1) == 1) 

    def runTest2(self): 
     self.assertFalse((self.p2 - self.p1) == 2) 


def load_tests(loader, tests, pattern): 
    test_cases = unittest.TestSuite() 
    for p1, p2 in [(1, 2), (3, 4)]: 
     clsname = 'TestCase_{}_{}'.format(p1, p2) 
     dct = { 
      'p1': p1, 
      'p2': p2, 
     } 
     cls = type(clsname, (GeneralTestCase,), dct) 
     test_cases.addTest(cls('runTest1')) 
     test_cases.addTest(cls('runTest2')) 
    return test_cases 

salidas

1 
2 
.. 
3 
4 
.. 
---------------------------------------------------------------------- 
Ran 4 tests in 0.000s 

OK 
Cuestiones relacionadas