unittest unit tests test skipif not examples equal python unit-testing

tests - Python: ¿Cómo ejecutar unittest.main() para todos los archivos fuente en un subdirectorio?



python unittest skipif (6)

A partir de Python 2.7, el descubrimiento de prueba está automatizado en el paquete unittest. De los unittest :

Unittest es compatible con el descubrimiento de prueba simple. Para ser compatible con el descubrimiento de prueba, todos los archivos de prueba deben ser módulos o paquetes importables desde el directorio de nivel superior del proyecto (esto significa que sus nombres de archivo deben ser identificadores válidos).

El descubrimiento de prueba se implementa en TestLoader.discover() , pero también se puede usar desde la línea de comando. El uso básico de la línea de comandos es:

cd project_directory python -m unittest discover

Por defecto, busca paquetes llamados test*.py , pero esto se puede cambiar para que pueda usar algo como

python -m unittest discover --pattern=*.py

En lugar de tu script test.py

Estoy desarrollando un módulo de Python con varios archivos fuente, cada uno con su propia clase de prueba derivada de unittest directamente en la fuente. Considere la estructura del directorio:

dirFoo/ test.py dirBar/ __init__.py Foo.py Bar.py

Para probar Foo.py o Bar.py, agregaría esto al final de los archivos fuente de Foo.py y Bar.py:

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

Y ejecute Python en cualquier fuente, es decir,

$ python Foo.py ........... ---------------------------------------------------------------------- Ran 11 tests in 2.314s OK

Idealmente, haría que "test.py" busque automágicamente dirBar para cualquier clase derivada de prueba de unidad y realice una llamada a "unittest.main ()". ¿Cuál es la mejor manera de hacer esto en la práctica?

Intenté usar Python para llamar a execfile para cada archivo * .py en dirBar, que se ejecuta una vez para el primer archivo .py encontrado y sale de la llamada test.py, y luego tengo que duplicar mi código agregando unittest.main () en cada archivo fuente - que viola los principios DRY.


Aquí está mi código de descubrimiento de prueba que parece hacer el trabajo. Quería asegurarme de poder extender las pruebas fácilmente sin tener que enumerarlas en ninguno de los archivos involucrados, pero también evitar escribir todas las pruebas en un solo archivo Übertest.

Entonces la estructura es

myTests.py testDir/ __init__.py testA.py testB.py

myTest.py se ve así:

import unittest if __name__ == ''__main__'': testsuite = unittest.TestLoader().discover(''.'') unittest.TextTestRunner(verbosity=1).run(testsuite)

Creo que esta es la solución más simple para escribir varios casos de prueba en un directorio. La solución requiere Python 2.7 o Python 3.


Deberías probar con la nose . Es una biblioteca para ayudar a crear pruebas y se integra con unittest o doctest . Todo lo que necesita hacer es ejecutar nosetests y encontrará todas sus nosetests por usted.

% nosetests # finds all tests in all subdirectories % nosetests tests/ # find all tests in the tests directory


En caso de que ayudara a alguien, aquí está el enfoque al que llegué para resolver este problema. Tuve el caso de uso donde tengo la siguiente estructura de directorio:

mypackage/ tests/ test_category_1/ tests_1a.py tests_1b.py ... test_category_2/ tests_2a.py tests_2b.py ... ...

y quiero que todo lo siguiente funcione de la manera más obvia y que se me puedan proporcionar los mismos argumentos de línea de comandos aceptados por unittest:

python -m mypackage.tests python -m mypackage.tests.test_category_1 python -m mypackage.tests.test_category_1.tests_1a

La solución fue configurar mypackage/tests/__init__.py esta manera:

import unittest def prepare_load_tests_function (the__path__): test_suite = unittest.TestLoader().discover(the__path__[0]) def load_tests (_a, _b, _c): return test_suite return load_tests

y para configurar mypackage/tests/__main__.py esta manera:

import unittest from . import prepare_load_tests_function, __path__ load_tests = prepare_load_tests_function(__path__) unittest.main()

y copiar y pegar un __init__.py vacío y el siguiente __main__.py en cada mypackage/tests/test_category_n/ :

import unittest from .. import prepare_load_tests_function from . import __path__ load_tests = prepare_load_tests_function(__path__) unittest.main()

y también para agregar el estándar if __name__ == ''__main__'': unittest.main() en cada archivo de prueba real.

(Funciona para mí en Python 3.3 en Windows, ymmv.)


Sabía que había una solución obvia:

dirFoo/ __init__.py test.py dirBar/ __init__.py Foo.py Bar.py

Contenido de dirFoo / test.py

from dirBar import * import unittest if __name__ == "__main__": unittest.main()

Ejecute las pruebas:

$ python test.py ........... ---------------------------------------------------------------------- Ran 11 tests in 2.305s OK

Perdón por la pregunta tonta.


Se me ocurrió un fragmento que puede hacer lo que quieras. Recorre un camino que proporciona en busca de paquetes / módulos de Python y acumula un conjunto de suites de prueba de esos módulos, que luego ejecuta de una sola vez.

Lo bueno de esto es que funcionará en todos los paquetes anidados en el directorio que especifique, y no tendrá que cambiar manualmente las importaciones a medida que agrega nuevos componentes.

import logging import os import unittest MODULE_EXTENSIONS = set(''.py .pyc .pyo''.split()) def unit_test_extractor(tup, path, filenames): """Pull ``unittest.TestSuite``s from modules in path if the path represents a valid Python package. Accumulate results in `tup[1]`. """ package_path, suites = tup logging.debug(''Path: %s'', path) logging.debug(''Filenames: %s'', filenames) relpath = os.path.relpath(path, package_path) relpath_pieces = relpath.split(os.sep) if relpath_pieces[0] == ''.'': # Base directory. relpath_pieces.pop(0) # Otherwise, screws up module name. elif not any(os.path.exists(os.path.join(path, ''__init__'' + ext)) for ext in MODULE_EXTENSIONS): return # Not a package directory and not the base directory, reject. logging.info(''Base: %s'', ''.''.join(relpath_pieces)) for filename in filenames: base, ext = os.path.splitext(filename) if ext not in MODULE_EXTENSIONS: # Not a Python module. continue logging.info(''Module: %s'', base) module_name = ''.''.join(relpath_pieces + [base]) logging.info(''Importing from %s'', module_name) module = __import__(module_name) module_suites = unittest.defaultTestLoader.loadTestsFromModule(module) logging.info(''Got suites: %s'', module_suites) suites += module_suites def get_test_suites(path): """:return: Iterable of suites for the packages/modules present under :param:`path`. """ logging.info(''Base path: %s'', package_path) suites = [] os.path.walk(package_path, unit_test_extractor, (package_path, suites)) logging.info(''Got suites: %s'', suites) return suites if __name__ == ''__main__'': logging.basicConfig(level=logging.WARN) package_path = os.path.dirname(os.path.abspath(__file__)) suites = get_test_suites(package_path) for suite in suites: unittest.TextTestRunner(verbosity=2).run(suite)