web-dev-qa-db-fra.com

S'assurer que py.test inclut le répertoire d'application dans sys.path

J'ai une structure de répertoire de projet comme suit (qui je pense est assez standard):

my_project
    setup.py
    mypkg
        __init__.py
        foo.py
    tests
        functional
            test_f1.py
        unit
            test_u1.py

J'utilise py.test pour mon framework de test, et je m'attends à pouvoir exécuter py.test tests quand dans le my_project répertoire pour exécuter mes tests. Cela fonctionne en effet, jusqu'à ce que j'essaie d'importer mon code d'application en utilisant (par exemple) import mypkg dans un test. À ce stade, j'obtiens l'erreur "Aucun module nommé mypkg". En faisant un peu d'enquête, il semble que py.test exécute les tests avec le répertoire du fichier de test dans sys.path, mais pas le répertoire que py.test a été exécuté depuis.

Afin de contourner ce problème, j'ai ajouté un conftest.py fichier dans mon répertoire tests, contenant le code suivant:

import sys, os

# Make sure that the application source directory (this directory's parent) is
# on sys.path.

here = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, here)

Cela semble fonctionner, mais est-ce un bon moyen de s'assurer que les tests voient le code de l'application? Y a-t-il une meilleure façon d'y parvenir, ou est-ce que je fais quelque chose de mal dans la façon dont j'ai structuré mon projet?

J'ai examiné d'autres projets utilisant py.test (par exemple, pip) mais je ne vois pas de code qui fait quelque chose comme ça, et pourtant j'exécute py.test tests semble fonctionner là-bas. Je ne sais pas trop pourquoi, mais je crains qu'ils n'aient pu obtenir le même résultat d'une manière plus simple.

J'ai regardé dans le py.test documentation, mais je ne vois pas d'explication de ce problème ni de l'approche recommandée pour y faire face.

45
Paul Moore

Comme vous le dites vous-même, py.test suppose que vous avez correctement configuré PYTHONPATH. Il existe plusieurs façons d'y parvenir:

  • Donnez à votre projet un fichier setup.py et utilisez pip install -e . dans un virtualenv pour ce projet. Il s'agit probablement de la méthode standard.

  • En variante, si vous avez un virtualenv mais pas de setup.py, utilisez la fonction de votre venv pour ajouter le répertoire des projets sur sys.path, par ex. pew add . si vous utilisez un banc, ou add2virtualenv . si vous utilisez virtualenv et les extensions de virtualenvwrapper.

  • Si vous aimez toujours le répertoire de travail actuel sur sys.path, vous pouvez simplement toujours exporter PYTHONPATH='' dans votre Shell. C'est-à-dire que la chaîne vide sur sys.path qui python interprétera comme le répertoire de travail actuel. Ceci est cependant potentiellement un danger pour la sécurité.

  • Mon hack préféré, abusez de la façon dont py.test charge les fichiers conftest: mettez un conftest.py dans le répertoire de niveau supérieur du projet.

La raison pour laquelle py.test se comporte de cette façon est de faciliter l'exécution des tests dans un répertoire tests/d'une extraction avec un package installé. S'il ajoutait inconditionnellement le répertoire du projet au PYTHONPATH, cela ne serait plus possible.

43
flub

La réponse est en fait beaucoup plus facile, comme on le voit ici .

Il vous suffit d'ajouter un __init__.py à votre répertoire de test et à chacun de ses sous-répertoires, comme ceci;

tests/__init__.py
tests/functional/__init__.py
tests/unit/__init__.py
8
sleepycal

La manière la plus simple de le faire est, dans le répertoire terminal/cmd, de changer le répertoire parent, (par exemple dans ce cas cd C:/.../my_project).

Exécutez ensuite: python -m pytest --cov=mypkg tests

Pas besoin de jouer avec la variable d'environnement PYTHONPATH. En exécutant avec python -m pytest, il ajoute automatiquement le répertoire courant à sys.path.

6
A H