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_methodpruebaif __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
unittestpaquete de biblioteca estándar tiene elsubTestadministrador 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 utilizadaunittestpara 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):[...]dctlugar 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.pycon 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.testunittesta py.test. Solía tenerTestCaseclases 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.testes 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 elunittestmó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
setupfunción de personalización por prueba.También es posible pasar
nosetestpará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__listyb__listSalida 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_methodsfunción. Debería serdef _add_test_methods, creoSimplemente use metaclases, como se ve aquí;
Salida:
fuente
Puedes usar clases
TestSuitepersonalizadasTestCase.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
TestGeneratorclase se puede utilizar para generar diferentes conjuntos de casos de prueba comoTestCluster.TestClusterpuede considerarse como una implementación de laTestGeneratorinterfaz.fuente
Esta solución funciona con
unittestynosepara 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 elmetaclasspará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
setUpClassacceso a los atributos asignados dinámicamente.Salidas
fuente
Solo para lanzar otra solución en la mezcla;)
Esto es efectivamente lo mismo
parameterizedque 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