write seqio read descargar bio python unit-testing nose py.test unittest2

seqio - read fasta python



¿Cómo ejecutar unittest discover de "python setup.py test"? (7)

Estoy intentando descubrir cómo hacer que python setup.py test ejecute el equivalente de python -m unittest discover . No quiero usar un script run_tests.py y no quiero usar ninguna herramienta de prueba externa (como nose o py.test ). Está bien si la solución solo funciona en Python 2.7.

En setup.py , creo que necesito agregar algo a los test_suite y / o test_loader en config, pero parece que no puedo encontrar una combinación que funcione correctamente:

config = { ''name'': name, ''version'': version, ''url'': url, ''test_suite'': ''???'', ''test_loader'': ''???'', }

¿Es posible usar solo unittest integrado en python 2.7?

FYI, mi estructura de proyecto se ve así:

project/ package/ __init__.py module.py tests/ __init__.py test_module.py run_tests.py <- I want to delete this setup.py

Actualización : Esto es posible con unittest2 pero quiero encontrar algo equivalente usando solo unittest

Desde https://pypi.python.org/pypi/unittest2

unittest2 incluye un recopilador de prueba compatible con herramientas de configuración muy básicas. Especifique test_suite = ''unittest2.collector'' en su setup.py. Esto inicia el descubrimiento de prueba con los parámetros predeterminados del directorio que contiene setup.py, por lo que quizás sea más útil como ejemplo (vea unittest2 / collector.py).

Por ahora, solo estoy usando un script llamado run_tests.py , pero espero poder deshacerme de esto pasando a una solución que solo usa la python setup.py test .

Aquí está el run_tests.py que espero eliminar:

import unittest if __name__ == ''__main__'': # use the default shared TestLoader instance test_loader = unittest.defaultTestLoader # use the basic test runner that outputs to sys.stderr test_runner = unittest.TextTestRunner() # automatically discover all tests in the current dir of the form test*.py # NOTE: only works for python 2.7 and later test_suite = test_loader.discover(''.'') # run the test suite test_runner.run(test_suite)


Desde la creación y distribución de paquetes con SetupTools (énfasis mío):

Banco de pruebas

Una cadena que nombra una subclase unittest.TestCase (o un paquete o módulo que contiene uno o más de ellos, o un método de dicha subclase), o que nombra una función a la que se puede llamar sin argumentos y devuelve un unittest.TestSuite .

Por lo tanto, en setup.py agregaría una función que devuelve TestSuite:

import unittest def my_test_suite(): test_loader = unittest.TestLoader() test_suite = test_loader.discover(''tests'', pattern=''test_*.py'') return test_suite

Luego, debe especificar la setup del comando de setup siguiente manera:

setup( ... test_suite=''setup.my_test_suite'', ... )


El módulo de unittest biblioteca estándar de Python admite el descubrimiento (en Python 2.7 y posterior, y Python 3.2 y posterior). Si puede asumir esas versiones mínimas, puede agregar el argumento de línea de comando de discover comando unittest .

Solo se necesita una pequeña modificación para setup.py :

import setuptools.command.test from setuptools import (find_packages, setup) class TestCommand(setuptools.command.test.test): """ Setuptools test command explicitly using test discovery. """ def _test_args(self): yield ''discover'' for arg in super(TestCommand, self)._test_args(): yield arg setup( ... cmdclass={ ''test'': TestCommand, }, )


Esto no eliminará run_tests.py, pero lo hará funcionar con setuptools. Añadir:

class Loader(unittest.TestLoader): def loadTestsFromNames(self, names, _=None): return self.discover(names[0])

Luego en setup.py: (supongo que estás haciendo algo como setup(**config) )

config = { ... ''test_loader'': ''run_tests:Loader'', ''test_suite'': ''.'', # your start_dir for discover() }

El único inconveniente que veo es que está doblando la semántica de loadTestsFromNames , pero el comando de prueba setuptools es el único consumidor y lo llama de una manera específica .


No necesitas config para que esto funcione. Básicamente, hay dos formas principales de hacerlo:

La manera rápida

Cambie el nombre de su test_module.py a module_test.py (básicamente agregue _test como un sufijo para las pruebas de un módulo en particular), y python lo encontrará automáticamente. Solo asegúrate de agregar esto a setup.py :

from setuptools import setup, find_packages setup( ... test_suite = ''tests'', ... )

El largo camino

A continuación, le mostramos cómo hacerlo con su estructura de directorio actual:

project/ package/ __init__.py module.py tests/ __init__.py test_module.py run_tests.py <- I want to delete this setup.py

En las tests/__init__.py , desea importar la prueba de unidad y la secuencia de prueba de su unidad test_module y luego crear una función para ejecutar las pruebas. En tests/__init__.py , escribe algo como esto:

import unittest import test_module def my_module_suite(): loader = unittest.TestLoader() suite = loader.loadTestsFromModule(test_module) return suite

La clase TestLoader tiene otras funciones además de loadTestsFromModule . Puede ejecutar dir(unittest.TestLoader) para ver los otros, pero este es el más simple de usar.

Dado que la estructura de su directorio es tal, probablemente querrá que test_module pueda importar su script de module . Es posible que ya haya hecho esto, pero en caso de que no lo haya hecho, podría incluir la ruta primaria para que pueda importar el módulo del package y el script del module . En la parte superior de tu test_module.py , escribe:

import os, sys sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ''..''))) import unittest import package.module ...

Finalmente, en setup.py , incluye el módulo de tests y ejecuta el comando que creaste, my_module_suite :

from setuptools import setup, find_packages setup( ... test_suite = ''tests.my_module_suite'', ... )

Luego, solo ejecuta la python setup.py test .

Aquí hay una sample alguien hizo como referencia.


Otra solución menos que ideal ligeramente inspirada por http://hg.python.org/unittest2/file/2b6411b9a838/unittest2/collector.py

Agregue un módulo que devuelva TestSuite de pruebas descubiertas. Luego configure la configuración para llamar a ese módulo.

project/ package/ __init__.py module.py tests/ __init__.py test_module.py discover_tests.py setup.py

Aquí está discover_tests.py :

import os import sys import unittest def additional_tests(): setup_file = sys.modules[''__main__''].__file__ setup_dir = os.path.abspath(os.path.dirname(setup_file)) return unittest.defaultTestLoader.discover(setup_dir)

Y aquí está setup.py :

try: from setuptools import setup except ImportError: from distutils.core import setup config = { ''name'': ''name'', ''version'': ''version'', ''url'': ''http://example.com'', ''test_suite'': ''discover_tests'', } setup(**config)


Si usa py27 + o py32 +, la solución es bastante simple:

test_suite="tests",


Una posible solución es simplemente extender el comando de test para distutils y setuptools / distribute . Esto parece un kluge total y mucho más complicado de lo que yo preferiría, pero parece descubrir y ejecutar correctamente todas las pruebas en mi paquete al ejecutar la python setup.py test . Me estoy retrasando al seleccionar esto como la respuesta a mi pregunta con la esperanza de que alguien proporcione una solución más elegante :)

(Inspirado por https://docs.pytest.org/en/latest/goodpractices.html#integrating-with-setuptools-python-setup-py-test-pytest-runner )

Ejemplo setup.py :

try: from setuptools import setup except ImportError: from distutils.core import setup def discover_and_run_tests(): import os import sys import unittest # get setup.py directory setup_file = sys.modules[''__main__''].__file__ setup_dir = os.path.abspath(os.path.dirname(setup_file)) # use the default shared TestLoader instance test_loader = unittest.defaultTestLoader # use the basic test runner that outputs to sys.stderr test_runner = unittest.TextTestRunner() # automatically discover all tests # NOTE: only works for python 2.7 and later test_suite = test_loader.discover(setup_dir) # run the test suite test_runner.run(test_suite) try: from setuptools.command.test import test class DiscoverTest(test): def finalize_options(self): test.finalize_options(self) self.test_args = [] self.test_suite = True def run_tests(self): discover_and_run_tests() except ImportError: from distutils.core import Command class DiscoverTest(Command): user_options = [] def initialize_options(self): pass def finalize_options(self): pass def run(self): discover_and_run_tests() config = { ''name'': ''name'', ''version'': ''version'', ''url'': ''http://example.com'', ''cmdclass'': {''test'': DiscoverTest}, } setup(**config)