Tengo algún tipo de datos de prueba y quiero crear una prueba unitaria para cada elemento. Mi primera idea fue hacerlo así:
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 maneja todos los datos en una prueba. Me gustaría generar una prueba para cada artículo sobre la marcha. ¿Alguna sugerencia?
python
unit-testing
parameterized-unit-test
Peter Hoffmann
fuente
fuente
Respuestas:
Esto se llama "parametrización".
Existen varias herramientas que respaldan este enfoque. P.ej:
El código resultante se ve así:
Lo que generará las pruebas:
Por razones históricas, dejaré la respuesta original alrededor de 2008):
Yo uso algo como esto:
fuente
.__name__ =
que habilitar la.exact_method
pruebaif __name__ == '__main__'
condicional? Seguramente debería salir de esto para ejecutarse en el momento de la importación (recordando que los módulos de Python solo se importan una vez, incluso si se importan desde varios lugares diferentes)Usando unittest (desde 3.4)
Desde Python 3.4, el
unittest
paquete de biblioteca estándar tiene elsubTest
administrador de contexto.Ver la documentación:
Ejemplo:
También puede especificar un mensaje personalizado y valores de parámetros para
subTest()
:Usando la nariz
El marco de prueba de nariz es compatible con esto .
Ejemplo (el código a continuación es el contenido completo del archivo que contiene la prueba):
La salida del comando nosetests:
fuente
Esto se puede resolver con elegancia usando Metaclasses:
fuente
__new__
método en la metaclase se llama cuando se define la clase en sí, no cuando se crea la primera instancia. Me imagino que este método de crear dinámicamente métodos de prueba es más compatible con la introspección utilizadaunittest
para determinar cuántas pruebas hay en una clase (es decir, puede compilar la lista de pruebas antes de crear una instancia de esa clase).class TestSequence(unittest.TestCase, metaclass=TestSequenceMeta):[...]
dct
lugar dedict
? Usar palabras clave como nombres de variables es confuso y propenso a errores.A partir de Python 3.4 se han introducido subpruebas en unittest para este propósito. Consulte la documentación para más detalles. TestCase.subTest es un administrador de contexto que permite aislar afirmaciones en una prueba para que se informe un error con la información de los parámetros, pero no detiene la ejecución de la prueba. Aquí está el ejemplo de la documentación:
El resultado de una ejecución de prueba sería:
Esto también es parte de unittest2 , por lo que está disponible para versiones anteriores de Python.
fuente
setUp()
ytearDown()
no se ejecutan entre las subpruebas.)self.setUp()
en teoría se puede llamar manualmente desde la subprueba. En cuanto atearDown
, llamarlo automáticamente al final podría ser suficiente.load_tests es un mecanismo poco conocido introducido en 2.7 para crear dinámicamente un TestSuite. Con él, puede crear fácilmente pruebas parametrizadas.
Por ejemplo:
Ese código ejecutará todos los TestCases en TestSuite devueltos por load_tests. El mecanismo de descubrimiento no ejecuta automáticamente otras pruebas.
Alternativamente, también puede usar la herencia como se muestra en este ticket: http://bugs.python.org/msg151444
fuente
Se puede hacer usando pytest . Simplemente escriba el archivo
test_me.py
con contenido:Y ejecuta tu prueba con el comando
py.test --tb=short test_me.py
. Entonces la salida se verá así:¡Es simple! También PYtest tiene más funciones, como
fixtures
,mark
,assert
, etc ...fuente
py.test
unittest
a py.test. Solía tenerTestCase
clases base que podían crear dinámicamente niños con diferentes argumentos que almacenaban como variables de clase ... lo cual era un poco difícil de manejar.py.test
es yield_fixtures . Lo que puede hacer la configuración , devolver algunos datos útiles a la prueba y, una vez finalizada la prueba, realizar el desmontaje . Los accesorios también se pueden parametirizar .Usa la biblioteca ddt . Agrega decoradores simples para los métodos de prueba:
Esta biblioteca se puede instalar con
pip
. No requierenose
, y funciona excelente con elunittest
módulo de biblioteca estándar .fuente
Te beneficiaría probar la biblioteca TestScenarios .
fuente
También hay una hipótesis que agrega pruebas basadas en propiedad o fuzz: https://pypi.python.org/pypi/hypothesis
Este es un método de prueba muy poderoso.
fuente
@given()
macro dentro de la clase unittest.Puedes usar el plugin nose-ittr (
pip install nose-ittr
).Es muy fácil de integrar con las pruebas existentes, se requieren cambios mínimos (si los hay). También es compatible con la nariz. complemento multiprocesamiento de .
No es que también pueda tener una
setup
función de personalización por prueba.También es posible pasar
nosetest
parámetros como con su complemento incorporadoattrib
, de esta manera solo puede ejecutar una prueba específica con un parámetro específico:fuente
Utilizo metaclases y decoradores para generar pruebas. Puedes consultar mi implementación python_wrap_cases . Esta biblioteca no requiere ningún marco de prueba.
Su ejemplo:
Salida de consola:
También puedes usar generadores . Por ejemplo, este código genera todas las combinaciones posibles de pruebas con argumentos
a__list
yb__list
Salida de consola:
fuente
Me encontré con ParamUnittest el otro día cuando miraba el código fuente del radón ( ejemplo de uso en el repositorio de github ). Debería funcionar con otros marcos que extiendan TestCase (como Nose).
Aquí hay un ejemplo:
fuente
RESULTADO:
fuente
def add_test_methods
función. Debería serdef _add_test_methods
, creoSimplemente use metaclases, como se ve aquí;
Salida:
fuente
Puedes usar clases
TestSuite
personalizadasTestCase
.fuente
__init__
función.He descubierto que esto funciona bien para mis propósitos, especialmente si necesito generar pruebas que diferencien ligeramente los procesos en una recopilación de datos.
La
TestGenerator
clase se puede utilizar para generar diferentes conjuntos de casos de prueba comoTestCluster
.TestCluster
puede considerarse como una implementación de laTestGenerator
interfaz.fuente
Esta solución funciona con
unittest
ynose
para Python 2 y Python 3:fuente
Había estado teniendo problemas con un estilo muy particular de pruebas parametrizadas. Todas nuestras pruebas de Selenium pueden ejecutarse localmente, pero también deberían poder ejecutarse de forma remota en varias plataformas en SauceLabs. Básicamente, quería tomar una gran cantidad de casos de prueba ya escritos y parametrizarlos con la menor cantidad posible de cambios en el código. Además, necesitaba poder pasar los parámetros al método de configuración, algo para lo que no he visto ninguna solución en ningún otro lado.
Esto es lo que se me ocurrió:
Con esto, todo lo que tenía que hacer era agregar un decorador simple @sauce_labs () a cada TestCase antiguo normal, y ahora cuando los ejecuta, se envuelven y se reescriben, 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 self / plataforma. plataforma para ejecutar, incluso en LoginTests.setUp, que es crucial para mi tarea ya que ahí es donde se inicializa la conexión a SauceLabs.
De todos modos, ¡espero que esto pueda ser de ayuda para alguien que busque hacer una parametrización "global" similar de sus pruebas!
fuente
Las respuestas basadas en metaclases todavía funcionan en Python3, pero en lugar del
__metaclass__
atributo uno tiene que usar elmetaclass
parámetro, como en:fuente
La metaprogramación es divertida, pero puede ponerse en camino. La mayoría de las soluciones aquí dificultan:
Entonces, mi primera sugerencia es seguir la ruta simple / explícita (funciona con cualquier corredor de prueba):
Como no deberíamos repetirnos, mi segunda sugerencia se basa en la respuesta de @ Javier: adoptar las pruebas basadas en propiedades. Biblioteca de hipótesis:
tiene muchas más características interesantes (estadísticas, resultados de pruebas adicionales, ...)
clase TestSequence (unittest.TestCase):
Para probar sus ejemplos específicos, simplemente agregue:
Para ejecutar solo un ejemplo en particular, puede comentar los otros ejemplos (el ejemplo proporcionado se ejecutará primero). Es posible que desee utilizar
@given(st.nothing())
. Otra opción es reemplazar todo el bloque por:Ok, no tienes nombres de prueba distintos. Pero tal vez solo necesites:
Ejemplo más divertido
fuente
Súper tarde a la fiesta, pero tuve problemas para hacer que esto funcione
setUpClass
.Aquí hay una versión de la respuesta de @ Javier que da
setUpClass
acceso a los atributos asignados dinámicamente.Salidas
fuente
Solo para lanzar otra solución en la mezcla;)
Esto es efectivamente lo mismo
parameterized
que se mencionó anteriormente, pero específico paraunittest
:Ejemplo de uso:
fuente
Además de usar setattr, podemos usar load_tests desde python 3.2. Consulte la publicación del blog blog.livreuro.com/en/coding/python/how-to-generate-discoverable-unit-tests-in-python-dynamically/
fuente
Lo siguiente es mi solución. Encuentro esto útil cuando: 1. Debería funcionar para unittest. Testcase y unittest discover 2. Tener un conjunto de pruebas para ejecutar para diferentes configuraciones de parámetros. 3. Muy simple sin dependencia de otros paquetes de importación unittest
fuente
fuente