Intento organizar mis proyectos de Python usando una estructura de carpetas. Cuando necesito hacer pruebas, uso algo como lo siguiente.
. |-- src | |-- b.py | `-- main.py `-- tests `-- test_main.py
Solo hay un gran problema con este enfoque. Pytest no se ejecutará si main.py
está importando b.py
Hasta ahora, he intentado colocar archivos __init__.py
vacíos dentro de las carpetas src
y tests
, tanto de forma independiente como conjunta, pero cualquiera de ellos parece funcionar.
Me parece que este es un proyecto bastante estándar, pero no he podido encontrar una solución en línea. ¿Debo usar una estructura de carpetas diferente? ¿Hay alguna forma recomendada de usar pytest con este tipo de proyectos?
Este es el contenido de los archivos:
# b.py def triplicate(x): return x * 3
# main.py from b import triplicate def duplicate(x): return x * 2
# test_main.py from src.main import duplicate def test_duplicate(): assert duplicate(2) == 4
Y este es el error que me sale al ejecutar pytest:
==================================================================================================== ERRORS ==================================================================================================== _____________________________________________________________________________________ ERROR collecting tests/test_main.py ______________________________________________________________________________________ ImportError while importing test module 'C:\Users\edwar\test_pytest\tests\test_main.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: c:\python39\lib\importlib\__init__.py:127: in import_module return _bootstrap._gcd_import(name[level:], package, level) tests\test_main.py:1: in <module> from src.main import duplicate src\main.py:1: in <module> from b import triplicate E ModuleNotFoundError: No module named 'b' =========================================================================================== short test summary info ============================================================================================ ERROR tests/test_main.py !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! =============================================================================================== 1 error in 0.15s ===============================================================================================
Puede colocar sus archivos de origen en el directorio raíz y ajustar las rutas de importación como tales:
principal.py
# main.py from stackoverflow.b import triplicate def duplicate(x): return x * 2
b.py
# b.py def triplicate(x): return x * 3
test_main.py
# test_main.py from stackoverflow.main import duplicate def test_duplicate(): assert duplicate(2) == 4
Luego ejecutando pytest .
desde el directorio raíz stackoverflow
:
collected 1 item tests\test_main.py . [100%] ====================================================================================== 1 passed in 0.03s =======================================================================================
O, si desea mantener la carpeta src
, su importación sería esta:
from stackoverflow.src.b import triplicate
Python usa la 'variable de entorno' PYTHONPATH
para buscar fuentes desde las cuales importar código. De forma predeterminada, el directorio en el que ejecuta un programa de python se incluye automáticamente, pero desea incluir algo como esto cuando realiza la prueba:
PYTHONPATH=$PYTHONPATH,../src python test_main.py
Esto es si está ejecutando una prueba desde el directorio de origen. Herramientas como IntelliJ (PyCharm) le permitirán agregar esto como un valor en su invocación de prueba. Alternativamente, puede usar export PYTHONPATH=...
. (Tenga en cuenta que esto es para un entorno * nix, su kilometraje en Windows puede variar).
El resultado es que se cargarán todos los directorios de PYTHONPATH
y Python intentará usarlo como "raíz" para los módulos que intente importar. Su estructura básica de directorios es la más idiomática.
PYTHONPATH
correctamente.PYTHONPATH
se modifica y se usa 'bajo el capó'.src
al ejecutar pruebas de pytest
.autoenv
(una biblioteca de Python) para habilitar el uso de archivos .env
para administrar esto por usted (al menos dentro de una configuración de virtualenv
, una buena idea en general).setup.py
también es idiomático para incluir muchos módulos y puede proporcionar una ruta más conveniente para la situación que está manejando.