python - resueltos - Prueba de unidad recursiva descubrir
recursividad en c++ pdf (2)
Al hacer un poco de excavación, parece que mientras los módulos más profundos sigan siendo importantes, se descubrirán a través de python -m unittest discover
. La solución, entonces, era simplemente agregar un archivo __init__.py
a cada directorio para hacerlos paquetes.
.
├── LICENSE
├── models
│ └── __init__.py
├── README.md
├── requirements.txt
├── tc.py
├── tests
│ ├── db
│ │ ├── __init__.py # NEW
│ │ └── test_employee.py
│ ├── __init__.py # NEW
│ └── test_tc.py
└── todo.txt
Mientras cada directorio tenga un __init__.py
, python -m unittest discover
puede importar el módulo test_*
relevante.
Tengo un paquete con un directorio "pruebas" en el que estoy almacenando mis pruebas unitarias. Mi paquete se ve como:
.
├── LICENSE
├── models
│ └── __init__.py
├── README.md
├── requirements.txt
├── tc.py
├── tests
│ ├── db
│ │ └── test_employee.py
│ └── test_tc.py
└── todo.txt
Desde el directorio de mi paquete, quiero poder encontrar las tests/test_tc.py
y las tests/db/test_employee.py
. Prefiero no tener que instalar una biblioteca de terceros ( nose
o etc.) o tengo que crear manualmente un TestSuite
para ejecutar esto.
¿Seguramente hay una manera de decirle a unittest discover
no debe dejar de buscar una vez que se encuentra una prueba? python -m unittest discover -s tests
encontrarán las tests/test_tc.py
y python -m unittest discover -s tests/db
encontrarán las tests/db/test_employee.py
. ¿No hay una manera de encontrar ambos?
Si está de acuerdo con agregar un archivo __init__.py
dentro de las pruebas, puede poner allí una función load_tests
que manejará el descubrimiento por usted.
Si el nombre de un paquete de prueba (directorio con
__init__.py
) coincide con el patrón, el paquete verificará la función ''load_tests''. Si esto existe, se llamará con cargador, pruebas, patrón.Si existe load_tests, entonces el descubrimiento no retrocede en el paquete, load_tests es responsable de cargar todas las pruebas en el paquete.
Estoy lejos de estar seguro de que esta es la mejor manera, pero una forma de escribir esa función sería:
import os
import pkgutil
import inspect
import unittest
# Add *all* subdirectories to this module''s path
__path__ = [x[0] for x in os.walk(os.path.dirname(__file__))]
def load_tests(loader, suite, pattern):
for imp, modname, _ in pkgutil.walk_packages(__path__):
mod = imp.find_module(modname).load_module(modname)
for memname, memobj in inspect.getmembers(mod):
if inspect.isclass(memobj):
if issubclass(memobj, unittest.TestCase):
print("Found TestCase: {}".format(memobj))
for test in loader.loadTestsFromTestCase(memobj):
print(" Found Test: {}".format(test))
suite.addTest(test)
print("=" * 70)
return suite
Bastante feo, estoy de acuerdo.
Primero, agregue todos los subdirectorios a la ruta de los paquetes de prueba ( Docs ).
Luego, usa pkgutil
para recorrer el camino, buscando paquetes o módulos.
Cuando encuentra uno, luego verifica los miembros del módulo para ver si son clases, y si son clases, si son subclases de unittest.TestCase
. Si lo son, las pruebas dentro de las clases se cargan en el conjunto de pruebas.
Así que ahora, desde dentro de la raíz de su proyecto, puede escribir
python -m unittest discover -p tests
Usando el interruptor de patrón -p
. Si todo va bien, verás lo que vi, que es algo así como:
Found TestCase: <class ''test_tc.TestCase''>
Found Test: testBar (test_tc.TestCase)
Found Test: testFoo (test_tc.TestCase)
Found TestCase: <class ''test_employee.TestCase''>
Found Test: testBar (test_employee.TestCase)
Found Test: testFoo (test_employee.TestCase)
======================================================================
....
----------------------------------------------------------------------
Ran 4 tests in 0.001s
OK
Que es lo que se esperaba, cada uno de mis dos archivos de ejemplo contenía dos pruebas, testFoo
y testBar
cada una.
Edición: después de algunas excavaciones más, parece que podría especificar esta función como:
def load_tests(loader, suite, pattern):
for imp, modname, _ in pkgutil.walk_packages(__path__):
mod = imp.find_module(modname).load_module(modname)
for test in loader.loadTestsFromModule(mod):
print("Found Tests: {}".format(test._tests))
suite.addTests(test)
Esto utiliza el método loader.loadTestsFromModule()
lugar del método loader.loadTestsFromTestCase()
que usé anteriormente. Todavía modifica la ruta del paquete de tests
y lo recorre en busca de módulos, lo que creo que es la clave aquí.
La salida se ve un poco diferente ahora, ya que estamos agregando un testuite encontrado a la vez a nuestra suite
principal de testsuite:
python -m unittest discover -p tests
Found Tests: [<test_tc.TestCase testMethod=testBar>, <test_tc.TestCase testMethod=testFoo>]
Found Tests: [<test_employee.TestCase testMethod=testBar>, <test_employee.TestCase testMethod=testFoo>]
======================================================================
....
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK
Pero aún obtenemos las 4 pruebas que esperábamos, en ambas clases, en ambos subdirectorios.