2011-07-12 7 views
55

Esta es una pregunta que se realiza con frecuencia en diferentes formas, y suele obtener respuestas de "lol you're no lo está haciendo correctamente". Estoy bastante seguro de que es porque hay un escenario de sentido común que las personas (incluyéndome a mí) están tratando de usar como una implementación, y la solución no es obvia (si no lo has hecho antes).Importaciones de Python para pruebas usando nose: cuál es la mejor práctica para las importaciones de módulos sobre el paquete actual

Aceptaría una respuesta que "deja volar de la botella".

Dadas

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

Cuando se inicia tests_sut.py:

import code.sut 

nosetests se ejecuta en el directorio raíz conduce a:

ImportError: No module named code.sut 

avenidas recorrida:

a) haz un pariente u cantar

from ..code import sut 

b) añadir a raíz del proyecto PYTHONPATH

c) utilizar el

sys.path.append 

para agregar la ruta .. antes de que las importaciones en el inicio de cada módulo de prueba.

d) sólo recuerda que hacer un

setup.py 

en el proyecto de instalación de los módulos en los site-packages antes de ejecutar las pruebas.


Así que el requisito es tener pruebas ubicadas debajo de la raíz del paquete de prueba que tienen acceso al proyecto. ¡Cada uno de los anteriores no me parece "natural", me ha resultado problemático o me parece que es demasiado trabajo!

En java esto funciona, pero básicamente a fuerza de su herramienta de compilación/IDE colocando todas sus clases en el classpath. Tal vez el problema es que estoy esperando "magia" de Python? Haber observado en las pruebas de Flab webframework, la opción d) parece ser la preferida.

En cualquier caso, las declaraciones a continuación que recomiendan una solución preferida eliminarían la sensación de "falta de naturalidad" en mi cuenta.

+0

relacionado con http://stackoverflow.com/questions/6323860/sibling-package-imports/6466139#6466139 aunque no es un duplicado exacto. – Evpok

+0

Esto resume maravillosamente el 80-90% de mi situación, si solo hubiera alguna aclaración sobre si virtualenv cambiaría o no la respuesta ... – sage

Respuesta

8

Ya ha respondido a su pregunta bastante bien ... D (instalar en la ubicación del sistema) es preferible para el código distribuible. Usualmente uso C (modifico sys.path) porque no quiero instalar todo el sistema de mis cientos de libs personalizadas. En teoría, A (importación relativa) parece más agradable, pero hay casos en los que falla. B (PYTHONPATH) está bien, realmente solo para fines de prueba en mi opinión.

Eso prácticamente resume todas las opciones. La opción que prefiera (Python sabe mágicamente dónde buscar) realmente no es una solución factible porque puede generar 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 punto (s) de entrada a su programa:

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

, pero supongo que mi punto de entrada (s!) Es el comando nosetests. Consideré ir por la ruta de escribir un contenedor nosetests llamando a nose.run después de agregar sys.path ... pero nuevamente se sentía antinatural. gracias por esto, me ayudará a seguir adelante. – leonigmig

+0

Si está ejecutando pruebas de nariz, entonces los puntos de entrada son los módulos individuales que se importan, y esto será muy incómodo. En este caso, puede encontrar que PYTHONPATH es la opción menos incómoda (como dije, está bien para fines de prueba). Siento tu dolor aquí. También espero que haya más personas que lo hagan parecer bien (o sugerir una solución mejor). – Luke

43

que tenían el mismo problema y encontrar una answer en una obra cuestión conexa para mí .

Simplemente elimine __init__.py en la raíz del proyecto.

+8

¡Gran respuesta! Tenía un viejo \ _ \ _ init \ _ \ _. Pyc sobrante que me causaba este problema. – frabcus

+0

Esto no me ayudó, ¿cómo se supone que funciona? – user541905

+1

@ user541905: porque nose intenta de forma inteligente poblar su 'sys.path'. Una buena explicación de django-nose en sí: https://github.com/django-nose/django-nose#upgrading-from-django--13-to-django-14 – furins

3

Sé que es una respuesta controlada y sigo pensando que es una buena razón para compartir otras alternativas :)

Hay una nose-pathmunge que le da un control para ajustar sys.path mientras se invoca nosestests.

Cuestiones relacionadas