La structure de répertoire très courante, même pour un simple module Python, semble être de séparer les tests unitaires dans leur propre test
répertoire:
new_project/
antigravity/
antigravity.py
test/
test_antigravity.py
setup.py
etc.
par exemple, consultez le guide du projet Python .
Ma question est simplement quelle est la manière habituelle d'exécuter les tests? Je soupçonne que cela est évident pour tout le monde sauf moi, mais vous ne pouvez pas simplement exécuter à python test_antigravity.py
partir du répertoire de test car son import antigravity
échouera car le module n'est pas sur le chemin.
Je sais que je pourrais modifier PYTHONPATH et d'autres astuces liées au chemin de recherche, mais je ne peux pas croire que ce soit le moyen le plus simple - c'est bien si vous êtes le développeur, mais pas réaliste de s'attendre à ce que vos utilisateurs l'utilisent s'ils veulent simplement vérifier que les tests sont qui passe.
L'autre alternative consiste simplement à copier le fichier de test dans l'autre répertoire, mais cela semble un peu stupide et manque le point de les avoir dans un répertoire séparé pour commencer.
Donc, si vous veniez de télécharger la source sur mon nouveau projet, comment exécuteriez-vous les tests unitaires? Je préférerais une réponse qui me permettrait de dire à mes utilisateurs: "Pour exécuter les tests unitaires, faites X."
la source
unittest
interface de ligne de commande comme décrit dans ma réponse ci-dessous afin que vous n'ayez pas à ajouter le répertoire au chemin.Réponses:
La meilleure solution à mon avis est d'utiliser l'
unittest
interface de ligne de commande qui ajoutera le répertoire ausys.path
afin que vous n'ayez pas à le faire (fait dans laTestLoader
classe).Par exemple pour une structure de répertoires comme celle-ci:
Vous pouvez simplement exécuter:
Pour une structure de répertoires comme la vôtre:
Et dans les modules de test à l'intérieur du
test
package, vous pouvez importer leantigravity
package et ses modules comme d'habitude:Exécution d'un seul module de test:
Pour exécuter un seul module de test, dans ce cas
test_antigravity.py
:Il vous suffit de référencer le module de test de la même manière que vous l'importez.
Exécution d'un scénario de test ou d'une méthode de test unique:
Vous pouvez également exécuter une seule
TestCase
ou une seule méthode de test:Exécution de tous les tests:
Vous pouvez également utiliser la découverte de test qui découvrira et exécutera tous les tests pour vous, ils doivent être des modules ou des packages nommés
test*.py
(peuvent être modifiés avec l'-p, --pattern
indicateur):Cela exécutera tous les
test*.py
modules à l'intérieur dutest
package.la source
python -m unittest discover
va rechercher et exécuter des tests dans letest
répertoire s'ils sont nomméstest*.py
. Si vous avez nommé le sous-répertoiretests
, utilisezpython -m unittest discover -s tests
et si vous avez nommé les fichiers de testantigravity_test.py
, utilisezpython -m unittest discover -s tests -p '*test.py'
Les noms de fichiers peuvent utiliser des traits de soulignement mais pas des tirets.ImportError: No module named 'test.test_antigravity'
raison d'un conflit avec le sous-module de test de la bibliothèque unittest. Peut-être qu'un expert peut confirmer et changer le nom du sous-répertoire de réponse par exemple, «tests» (pluriel).test_antigravity.py
lance toujours une erreur d'importation pour les deuximport antigravity
etfrom antigravity import antigravity
, ainsi. J'ai les deux__init_.py
fichiers et j'appellepython3 -m unittest discover
depuis lenew project
répertoire. Quoi d'autre pourrait-être faux?test/__init__.py
est crucial ici, même s'il est videtest
est spécial ... mais juste pour mémoire, ce n'est pas le cas. : Ppython -m unittest discover
fonctionne avec des fichiers de test danstests/
tout aussi bien quetest/
.La solution la plus simple pour vos utilisateurs consiste à fournir un script exécutable (
runtests.py
ou quelque chose de ce genre) qui amorce l'environnement de test nécessaire, y compris, si nécessaire, en ajoutantsys.path
temporairement votre répertoire de projet racine à . Cela ne nécessite pas que les utilisateurs définissent des variables d'environnement, quelque chose comme ça fonctionne bien dans un script d'amorçage:Vos instructions à vos utilisateurs peuvent alors être aussi simples que "
python runtests.py
".Bien sûr, si le chemin dont vous avez besoin est vraiment
os.path.dirname(__file__)
, vous n'avez pas du tout besoin de l'ajoutersys.path
; Python place toujours le répertoire du script en cours d'exécution au début desys.path
, donc selon votre structure de répertoire, il suffit de localiser votreruntests.py
au bon endroit.De plus, le module unittest dans Python 2.7+ (qui est rétroporté comme unittest2 pour Python 2.6 et versions antérieures) a désormais une détection de test intégrée, donc Nose n'est plus nécessaire si vous voulez une détection de test automatisée: vos instructions utilisateur peuvent être aussi simples que
python -m unittest discover
.la source
python -m pdb tests\test_antigravity.py
. Dans pdb, j'ai exécutésys.path.insert(0, "antigravity")
ce qui a permis à l'instruction d'importation de se résoudre comme si j'exécutais le module.Je crée généralement un script "exécuter les tests" dans le répertoire du projet (celui qui est commun au répertoire source et
test
) qui charge ma suite "Tous les tests". Il s'agit généralement de code standard, donc je peux le réutiliser de projet en projet.run_tests.py:
test / all_tests.py (de Comment puis-je exécuter tous les tests unitaires Python dans un répertoire? )
Avec cette configuration, vous pouvez en effet juste
include antigravity
dans vos modules de test. L'inconvénient est que vous auriez besoin de plus de code de support pour exécuter un test particulier ... Je les exécute tous à chaque fois.la source
run tests
script dans le répertoire du projet et j'ai trouvé un moyen beaucoup plus propre de le faire. Hautement recommandé.De l'article que vous avez lié à:
Peut-être devriez-vous regarder le nez comme il le suggère?
la source
J'ai eu le même problème, avec un dossier de tests unitaires séparé. À partir des suggestions mentionnées, j'ajoute le chemin source absolu à
sys.path
.L'avantage de la solution suivante est que l'on peut exécuter le fichier
test/test_yourmodule.py
sans changer d'abord dans le répertoire test:la source
si vous exécutez "python setup.py develop" alors le paquet sera dans le chemin. Mais vous ne voudrez peut-être pas faire cela car vous pourriez infecter votre installation de python système, c'est pourquoi des outils comme virtualenv et buildout existent.
la source
Solution / Exemple pour le module Python unittest
Étant donné la structure de projet suivante:
Vous pouvez exécuter votre projet à partir du répertoire racine avec
python project_name
, qui appelleProjectName/project_name/__main__.py
.Pour exécuter vos tests avec
python test
une exécution efficaceProjectName/test/__main__.py
, vous devez procéder comme suit:1) Transformez votre
test/models
répertoire en package en ajoutant un__init__.py
fichier. Cela rend les cas de test dans le sous-répertoire accessibles à partir dutest
répertoire parent .2) Modifiez votre chemin d'accès système
test/__main__.py
pour inclure leproject_name
répertoire.Vous pouvez désormais importer des éléments avec succès
project_name
dans vos tests.la source
Utilisez
setup.py develop
pour que votre répertoire de travail fasse partie de l'environnement Python installé, puis exécutez les tests.la source
invalid command 'develop'
et cette option n'est pas mentionnée si je demandesetup.py --help-commands
. Faut-il quelque chose ensetup.py
soi pour que cela fonctionne?import setuptools
dans monsetup.py
fichier. Mais je suppose que cela montre que cela ne fonctionnera pas tout le temps pour les modules d'autres personnes.pip install -e .
cela ajoute également le package à l'environnement Python sans copier la source, vous permettant de continuer à le modifier où il se trouve.pip install -e .
est exactement la même chose quepython setup.py develop
, il monkeypres juste votresetup.py
même si ce n'est pas le cas, donc cela fonctionne dans les deux cas.Si vous utilisez VS Code et que vos tests sont situés au même niveau que votre projet, l'exécution et le débogage de votre code ne fonctionnent pas immédiatement. Vous pouvez modifier votre fichier launch.json:
La ligne clé ici est envFile
À la racine de votre projet, ajoutez le fichier .env
À l'intérieur de votre fichier .env, ajoutez le chemin d'accès à la racine de votre projet. Cela ajoutera temporairement
chemin d'accès à votre projet et vous pourrez utiliser les tests unitaires de débogage de VS Code
la source
J'ai remarqué que si vous exécutez l'interface de ligne de commande la plus unitaire à partir de votre répertoire "src", les importations fonctionnent correctement sans modification.
Si vous souhaitez mettre cela dans un fichier batch dans votre répertoire de projet, vous pouvez le faire:
la source
J'ai le même problème depuis longtemps. Ce que j'ai récemment choisi, c'est la structure de répertoires suivante:
et dans le
__init__.py
script du dossier de test, j'écris ce qui suit:Le Makefile est extrêmement important pour partager le projet, car il applique correctement les scripts. Voici la commande que j'ai mise dans le Makefile:
Le Makefile est important non seulement à cause de la commande qu'il exécute mais aussi à cause de l' endroit où il l'exécute . Si vous voulez faire un cd dans les tests et le faire
python -m unittest discover .
, cela ne fonctionnerait pas car le script init dans unit_tests appelle os.getcwd (), qui pointerait alors vers le chemin absolu incorrect (qui serait ajouté à sys.path et il vous manquerait votre dossier source). Les scripts s'exécuteraient depuis que find trouve tous les tests, mais ils ne fonctionneraient pas correctement. Le Makefile est donc là pour éviter d'avoir à se souvenir de ce problème.J'aime vraiment cette approche car je n'ai pas à toucher mon dossier src, mes tests unitaires ou mes variables d'environnement et tout se passe bien.
Faites-moi savoir si vous les aimez.
J'espère que cela pourra aider,
la source
Voici la structure de mon projet:
J'ai trouvé préférable d'importer dans la méthode setUp ():
la source
J'utilise Python 3.6.2
Pour installer pytest :
sudo pip install pytest
Je n'ai défini aucune variable de chemin et mes importations n'échouent pas avec la même structure de projet "test".
J'ai commenté ce truc:
if __name__ == '__main__'
comme ceci:test_antigravity.py
la source
Il est possible d'utiliser un wrapper qui exécute certains tests ou tous les tests.
Par exemple:
ou pour exécuter tous les tests de manière récursive, utilisez globbing (
tests/**/*.py
) (activé parshopt -s globstar
).Le wrapper peut essentiellement utiliser
argparse
pour analyser les arguments comme:Chargez ensuite tous les tests:
puis ajoutez-les dans votre suite de tests (en utilisant
inspect
):et exécutez-les:
Consultez cet exemple pour plus de détails.
Voir aussi: Comment exécuter tous les tests unitaires Python dans un répertoire?
la source
Python 3+
Ajout à @Pierre
Utilisation d'une
unittest
structure de répertoires comme celle-ci:Pour exécuter le module de test
test_antigravity.py
:Ou un seul
TestCase
Obligatoire n'oubliez pas le
__init__.py
même si vide sinon ne fonctionnera pas.la source
Vous ne pouvez pas importer du répertoire parent sans un peu de vaudou. Voici encore une autre méthode qui fonctionne avec au moins Python 3.6.
Tout d'abord, ayez un fichier test / context.py avec le contenu suivant:
Ensuite, importez le fichier suivant dans le fichier test / test_antigravity.py:
Notez que la raison de cette clause try-except est que
Avec cette ruse, ils travaillent tous les deux.
Vous pouvez maintenant exécuter tous les fichiers de test dans le répertoire de test avec:
ou exécutez un fichier de test individuel avec:
Ok, ce n'est pas beaucoup plus joli que d'avoir le contenu de context.py dans test_antigravity.py, mais peut-être un peu. Les suggestions sont les bienvenues.
la source
Si vous avez plusieurs répertoires dans votre répertoire de test, vous devez ajouter à chaque répertoire un
__init__.py
fichier.Ensuite, pour exécuter chaque test à la fois, exécutez:
La source:
python -m unittest -h
la source
Ce script BASH exécutera le répertoire de test python unittest de n'importe où dans le système de fichiers, quel que soit le répertoire de travail dans lequel vous vous trouvez.
Ceci est utile lorsque vous restez dans le répertoire de travail
./src
ou./example
et vous avez besoin d'un test unitaire rapide:Pas besoin de
test/__init__.py
fichier pour surcharger votre package / surcharge de mémoire pendant la production.la source
De cette façon, vous pourrez exécuter les scripts de test où vous le souhaitez sans vous soucier des variables système de la ligne de commande.
Cela ajoute le dossier principal du projet au chemin python, avec l'emplacement trouvé par rapport au script lui-même, et non par rapport au répertoire de travail actuel.
Ajoutez cela en haut de tous vos scripts de test. Cela ajoutera le dossier principal du projet au chemin système, donc tout module importé qui fonctionne à partir de là fonctionnera désormais. Et peu importe d'où vous exécutez les tests.
Vous pouvez évidemment modifier le fichier project_path_hack pour qu'il corresponde à l'emplacement de votre dossier de projet principal.
la source
Si vous recherchez une solution en ligne de commande uniquement:
Basé sur la structure de répertoires suivante (généralisée avec un répertoire source dédié):
Windows : (en
new_project
)Consultez cette question si vous souhaitez l'utiliser dans une boucle for batch.
Linux : (en
new_project
)Avec cette approche, il est également possible d'ajouter plus de répertoires au PYTHONPATH si nécessaire.
la source
Vous devriez vraiment utiliser l'outil pip.
Utilisez
pip install -e .
pour installer votre package en mode développement. Il s'agit d'une très bonne pratique, recommandée par pytest (voir leur documentation sur les bonnes pratiques , où vous pouvez également trouver deux dispositions de projet à suivre).la source
pytest
est préférable d'exécuter des tests, en raison de la sortie de la console que vous obtenez, en couleur, avec des informations de trace de pile et des informations détaillées sur les erreurs d'assertion.