Estoy siguiendo las buenas prácticas de pytest o al menos eso creo . Sin embargo, pytest no puede encontrar mi módulo. Parece que no incluye el directorio actual en su PYTHONPATH
.
El archivo fuente:
def add(x, y): return x + y
El archivo de prueba:
import pytest from junk.ook import add def test_add_true(): assert add(1, 1) == 2
Y la salida del shell con un entorno virtual de Python 3 llamado "p3".
p3; pwd /home/usr/tmp/junk p3; ls total 0 0 junk/ 0 tests/ p3; ls junk total 4.0K 4.0K ook.py 0 __init__.py p3; ls tests total 4.0K 4.0K test_ook.py 0 __pycache__/ p3; pytest ============================= test session starts ============================== platform linux -- Python 3.4.5, pytest-3.4.1, py-1.5.2, pluggy-0.6.0 rootdir: /home/usr/tmp/junk, inifile: collected 0 items / 1 errors ==================================== ERRORS ==================================== ______________________ ERROR collecting tests/test_ook.py ______________________ ImportError while importing test module '/home/usr/tmp/junk/tests/test_ook.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: tests/test_ook.py:2: in <module> from junk.ook import add E ImportError: No module named 'junk' !!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!! =========================== 1 error in 0.08 seconds ============================ def test_add_true(): assert add(1, 1) == 2
Sin embargo, ejecutar lo siguiente funciona bien.
p3; python -m pytest tests/ ============================= test session starts ============================== platform linux -- Python 3.4.5, pytest-3.4.1, py-1.5.2, pluggy-0.6.0 rootdir: /home/usr/tmp/junk, inifile: collected 1 item tests/test_ook.py . [100%] =========================== 1 passed in 0.02 seconds ===========================
¿Qué estoy haciendo mal?
pythonpath
Recientemente, pytest
agregó un nuevo complemento principal que admite modificaciones de sys.path
a través del valor de configuración de pythonpath
. La solución es mucho más simple ahora y ya no requiere soluciones alternativas:
ejemplo pyproject.toml
:
[tool.pytest.ini_options] pythonpath = [ "." ]
ejemplo pytest.ini
:
[pytest] pythonpath = .
Las entradas de la ruta se calculan en relación con el rootdir, por lo tanto .
agrega el directorio junk
a sys.path
en este caso.
También se permiten múltiples entradas de ruta: para un diseño
junk/ ├── src/ | └── lib.py ├── junk/ │ ├── __init__.py │ └── ook.py └── tests ├── test_app.py └── test_lib.py
La configuración
[tool.pytest.ini_options] pythonpath = [ ".", "src", ]
o
[pytest] pythonpath = . src
agregará tanto el módulo lib
como el paquete junk
a sys.path
, por lo que
import junk import lib
ambos funcionarán.
Simplemente coloque un archivo conftest.py
vacío en el directorio raíz del proyecto:
$ pwd /home/usr/tmp/junk $ touch conftest.py
La estructura de su proyecto debe convertirse en:
junk ├── conftest.py ├── junk │ ├── __init__.py │ └── ook.py └── tests └── test_ook.py
Qué sucede aquí: cuando pytest
descubre un conftest.py
, modifica sys.path
para que pueda importar cosas del módulo conftest. Entonces, dado que ahora se encuentra un conftest.py
vacío en rootdir, pytest
se verá obligado a agregarlo a sys.path
. El efecto secundario de esto es que su módulo junk
se vuelve importable.
Simplemente agregue __init__.py
al directorio de tests
y a todos los directorios recursivamente dentro de él que contengan archivos de prueba.