Python importa para pruebas usando nose: ¿cuál es la mejor práctica para importar módulos por encima del paquete actual?

Esta es una pregunta que se realiza con frecuencia en diferentes formas y que a menudo obtiene respuestas de “jajaja, no lo estás haciendo correctamente”. Bastante seguro es porque hay un escenario de sentido común que las personas (incluido yo) están tratando de usar como una implementación, y la solución no es obvia (si no lo has hecho antes).

Aceptaría una respuesta que “permita que la mosca salga de la botella”.

Dado

project/ __init__.py /code __init__.py sut.py /tests __init__.py test_sut.py 

Donde test_sut.py comienza:

 import code.sut 

La ejecución de pruebas en el directorio raíz conduce a:

 ImportError: No module named code.sut 

Avenidas recorridas:

a) hacer un pariente usando

 from ..code import sut 

b) agregar la raíz del proyecto a PYTHONPATH

c) usar el

 sys.path.append 

para agregar la ruta .. antes de las importaciones al inicio de cada módulo de prueba.

d) solo recuerda hacer un

 setup.py 

en el proyecto para instalar los módulos en los paquetes de sitio antes de ejecutar pruebas.


Por lo tanto, el requisito es tener pruebas ubicadas debajo de la raíz del paquete de prueba que tengan acceso al proyecto. ¡Cada uno de los anteriores no me parece “natural”, ha resultado ser problemático o parece un trabajo demasiado duro!

En Java esto funciona, pero básicamente a fuerza de tu herramienta de construcción / IDE colocando todas tus clases en el classpath. Quizás el problema es que estoy esperando “magia” de Python? Como se ha señalado en las pruebas de webframework de Flask, la opción d) parece ser la preferida.

En cualquier caso, las declaraciones a continuación que recomiendan una solución preferida eliminarán la sensación de “antinaturalidad” por mi cuenta.

Ya ha respondido bastante bien a su pregunta. Se prefiere D (instalar en la ubicación del sistema) para el código distribuible. Normalmente uso C (modificar sys.path) porque no quiero instalaciones de todo el sistema de mis cientos de librerías personalizadas. En teoría, A (importación relativa) parece mejor, pero hay casos en los que falla. B (PYTHONPATH) está listo, en realidad solo para propósitos de prueba en mi opinión.

Eso resume bastante bien todas las opciones. La opción que prefieres (Python sabe mágicamente dónde buscar) realmente no es una solución viable porque puede dar lugar a resultados impredecibles, como la búsqueda automática de bibliotecas de proyectos no relacionados.

En mi opinión, lo mejor que puede hacer es poner esto en el (los) punto (s) de entrada de su progtwig:

 import sys, os sys.path = [os.path.abspath(os.path.dirname(__file__))] + sys.path 

Tuve el mismo problema y encontré una respuesta en un trabajo relacionado de preguntas para mí.

Simplemente quite el __init__.py en la raíz del proyecto.

Sé que hay una respuesta marcada y todavía creo que es una buena razón para compartir otras alternativas 🙂

Hay un nose-pathmunge que le da un control para configurar sys.path al invocar las nosestests .