web-dev-qa-db-fra.com

Problème PATH avec pytest 'ImportError: Aucun module nommé YadaYadaYada'

J'ai utilisé easy_install pour installer pytest sur un mac et j'ai commencé à écrire des tests pour un projet avec une structure de fichier similaire à celle-ci:

repo/
repo/app.py
repo/settings.py
repo/models.py
repo/tests/
repo/tests/test_app.py

lancez py.test alors que vous vous trouvez dans le répertoire repo, tout se comporte comme prévu

mais quand j'essaie la même chose sous Linux ou Windows (les deux ont pytest 2.2.3 sur eux), il aboie dès qu'il frappe sa première importation de quelque chose de mon chemin d'application. Disons par exemple from app import some_def_in_app

Dois-je modifier mon PATH pour exécuter py.test sur ces systèmes? Quelqu'un at-il vécu cela?

179
MattoTodd

Oui, le dossier source n'est pas dans le chemin de Python si vous cd dans le répertoire tests.

Vous avez 2 choix:

  1. Ajoutez le chemin manuellement aux fichiers de test, comme ceci:

    import sys, os
    myPath = os.path.dirname(os.path.abspath(__file__))
    sys.path.insert(0, myPath + '/../')
    
  2. Exécutez les tests avec env var PYTHONPATH=../.

71
Not_a_Golfer

Je ne sais pas pourquoi py.test n'ajoute pas le répertoire actuel dans le PYTHONPATH lui-même, mais voici une solution de contournement (à exécuter à partir de la racine de votre référentiel):

python -m pytest tests/

Cela fonctionne parce que Python ajoute pour vous le répertoire actuel dans PYTHONPATH.

214
Apteryx

J'ai eu le même problème. Je l'ai corrigé en ajoutant un fichier __init__.py vide à mon répertoire tests.

98
Aron Curzon

conftest solution

La solution la moins invasive consiste à ajouter un fichier vide nommé conftest.py dans le répertoire repo/:

$ touch repo/conftest.py

C'est ça. Nul besoin d'écrire un code personnalisé pour modifier le sys.path ou de ne pas oublier de faire glisser PYTHONPATH, ou de placer __init__.py dans des répertoires auxquels il n'appartient pas.

Le répertoire du projet après:

repo
├── conftest.py
├── app.py
├── settings.py
├── models.py
└── tests
     └── test_app.py

Explication

pytest recherche les modules conftest de la collection de tests afin de rassembler les hooks et les fixtures personnalisés. Pour importer les objets personnalisés, pytest ajoute le répertoire parent du conftest.py au sys.path. .

Autres structures de projet

Si vous avez une autre structure de projet, placez le conftest.py dans le répertoire racine du paquet (celui qui contient des paquetages mais n’est pas un paquet lui-même, donc ne contient pas un __init__.py), par exemple:

repo
├── conftest.py
├── spam
│   ├── __init__.py
│   ├── bacon.py
│   └── Egg.py
├── eggs
│   ├── __init__.py
│   └── sausage.py
└── tests
     ├── test_bacon.py
     └── test_Egg.py

src mise en page

Bien que cette approche puisse être utilisée avec la disposition src (placez conftest.py dans le répertoire src:):

repo
├── src
│   ├── conftest.py
│   ├── spam
│   │   ├── __init__.py
│   │   ├── bacon.py
│   │   └── Egg.py
│   └── eggs 
│       ├── __init__.py
│       └── sausage.py
└── tests
     ├── test_bacon.py
     └── test_Egg.py

attention, l'ajout de src à PYTHONPATH atténue le sens et les avantages de la mise en page src! Vous finirez par tester le code du référentiel et non le package installé. Si vous avez besoin de le faire, vous n’avez peut-être pas besoin du répertoire src.

Où aller en partant d'ici

Bien entendu, les modules conftest ne sont pas que des fichiers destinés à faciliter la découverte du code source; C’est là que toutes les améliorations spécifiques du projet du framework pytest et la personnalisation de votre suite de tests ont lieu. pytest a beaucoup d’informations sur conftest modules disséminés dans tout leur documentation ; commencer par conftest.py: plugins locaux par répertoire

De plus, SO pose une excellente question sur les modules conftest: Dans py.test, à quoi servent les fichiers conftest.py?

87
hoefling

Vous pouvez exécuter avec PYTHONPATH dans la racine du projet

PYTHONPATH=. py.test

Ou utilisez pip install comme import modifiable

pip install -e .   # install package using setup.py in editable mode
37
Ford Guo

Exécutez pytest lui-même en tant que module avec: python -m pytest tests

32
Stefano Messina

J'ai créé ceci comme réponse à votre question et à ma propre confusion. J'espère que ça aide. Faites attention à PYTHONPATH dans la ligne de commande py.test et dans le fichier tox.ini.

https://github.com/jeffmacdonald/pytest_test

Plus précisément: vous devez indiquer à py.test et à Tox où trouver les modules que vous incluez.

Avec py.test, vous pouvez faire ceci:

PYTHONPATH=. py.test

Et avec tox, ajoutez ceci à votre tox.ini:

[testenv]
deps= -r{toxinidir}/requirements.txt
commands=py.test
setenv =
    PYTHONPATH = {toxinidir}
19
Jeff MacDonald

J'ai commencé à avoir des erreurs bizarres ConftestImportFailure: ImportError('No module named ... alors que j'avais accidentellement ajouté le fichier __init__.py à mon répertoire src (qui n'était pas censé être un package Python, mais un conteneur de toutes les sources).

7
jbasko

Je l'ai corrigé en supprimant le __init__.py de niveau supérieur dans le dossier parent de mes sources.

3
Gonzalo

J'obtenais cette erreur à cause de quelque chose d'encore plus simple (on pourrait même dire trivial). Je n'avais pas installé le module pytest. Donc, un simple apt install python-pytest le corrige pour moi.

'pytest' aurait été répertorié dans setup.py en tant que dépendance de test. Assurez-vous d’installer également les exigences de test.

3
craq

J'ai eu un problème similaire. pytest n'a pas reconnu un module installé dans l'environnement dans lequel je travaillais.

Je l'ai résolu en installant également pytest dans le même environnement.

1
nocibambi

Pour moi, le problème était tests.py généré par Django avec le répertoire tests. Supprimer tests.py a résolu le problème.

1
Paweł Mucha

J'ai eu cette erreur car j'ai mal utilisé les importations relatives. Dans l'exemple OP, test_app.py devrait importer des fonctions en utilisant, par exemple,.

from repo.app import *

Même si des fichiers __init__.py sont dispersés dans la structure de fichiers, cela ne fonctionne pas et crée le type d'ImportError affiché, sauf si les fichiers et les fichiers de test sont insérés. le même répertoire.

from app import *

Voici un exemple de ce que j'ai eu à faire avec l'un de mes projets:

Voici la structure de mon projet:

microbit/
microbit/activity_indicator/activity_indicator.py
microbit/tests/test_activity_indicator.py

Pour pouvoir accéder à activity_indicator.py à partir de test_activity_indicator.py, je devais:

  • démarrez test_activity_indicatory.py avec l'importation relative correcte:
    from microbit.activity_indicator.activity_indicator import *
  • mettez les fichiers __init__.py dans la structure du projet:
    microbit/
    microbit/__init__.py
    microbit/activity_indicator/__init__.py
    microbit/activity_indicator/activity_indicator.py
    microbit/tests/__init__.py
    microbit/tests/test_activity_indicator.py
1
Oppy