Si vous écrivez une bibliothèque ou une application, où vont les fichiers de test unitaire?
Il est agréable de séparer les fichiers de test du code de l'application principale, mais il est gênant de les placer dans un sous-répertoire "tests" à l'intérieur du répertoire racine de l'application, car cela rend plus difficile l'importation des modules que vous testerez.
Y a-t-il une meilleure pratique ici?
python
unit-testing
code-organization
Lecture seulement
la source
la source
Réponses:
Pour un fichier
module.py
, le test unitaire doit normalement être appelétest_module.py
, selon les conventions de dénomination Pythonic.Il existe plusieurs endroits généralement acceptés
test_module.py
:module.py
.../tests/test_module.py
(au même niveau que le répertoire de code).tests/test_module.py
(un niveau sous le répertoire de code).Je préfère le n ° 1 pour sa simplicité à trouver les tests et à les importer. Quel que soit le système de construction que vous utilisez, vous pouvez facilement le configurer pour exécuter des fichiers à partir de
test_
. En fait, le modèle par défautunittest
utilisé pour la découverte de test esttest*.py
.la source
Un seul fichier de test
S'il n'y a qu'un seul fichier de test, il est recommandé de le placer dans un répertoire de niveau supérieur:
Exécutez le test dans CLI
De nombreux fichiers de test
Si possède de nombreux fichiers de test, placez-le dans un
tests
dossier:Exécutez le test dans CLI
Utilisation
unittest discovery
unittest discovery
trouvera tous les tests dans le dossier du package.Créer un dossier
__init__.py
danstests/
Exécutez le test dans CLI
Référence
pytest
Bonnes pratiques pour la disposition des testsunittest
Cadre de test unitaire
la source
Une pratique courante consiste à placer le répertoire tests dans le même répertoire parent que votre module / package. Donc, si votre module s'appelait foo.py, la disposition de votre répertoire ressemblerait à:
Bien sûr, il n'y a pas qu'une seule façon de procéder. Vous pouvez également créer un sous-répertoire de tests et importer le module à l'aide de l'importation absolue .
Partout où vous mettez vos tests, je vous recommande d'utiliser le nez pour les exécuter. Nose recherche dans vos répertoires des tests. De cette façon, vous pouvez mettre des tests là où ils ont le plus de sens sur le plan organisationnel.
la source
Nous avions la même question lors de l'écriture de Pythoscope ( https://pypi.org/project/pythoscope/ ), qui génère des tests unitaires pour les programmes Python. Nous avons interrogé les personnes sur la liste des tests en python avant de choisir un répertoire, il y avait beaucoup d'opinions différentes. Finalement, nous avons choisi de mettre un répertoire "tests" dans le même répertoire que le code source. Dans ce répertoire, nous générons un fichier de test pour chaque module dans le répertoire parent.
la source
J'ai également tendance à mettre mes tests unitaires dans le fichier lui-même, comme le note Jeremy Cantrell ci-dessus, même si j'ai tendance à ne pas mettre la fonction de test dans le corps principal, mais plutôt à tout mettre dans un
bloquer. Cela finit par ajouter de la documentation au fichier comme «exemple de code» pour savoir comment utiliser le fichier python que vous testez.
Je devrais ajouter, j'ai tendance à écrire des modules / classes très serrés. Si vos modules nécessitent un très grand nombre de tests, vous pouvez les mettre dans un autre, mais même dans ce cas, j'ajouterais quand même:
Cela permet à quiconque lit votre code source de savoir où chercher le code de test.
la source
De temps en temps, je me retrouve à vérifier le sujet du placement de test, et à chaque fois la majorité recommande une structure de dossiers séparée à côté du code de la bibliothèque, mais je trouve que chaque fois les arguments sont les mêmes et ne sont pas si convaincants. Je finis par mettre mes modules de test quelque part à côté des modules de base.
La principale raison de cette opération est la refactorisation .
Quand je déplace des choses, je veux que les modules de test se déplacent avec le code; il est facile de perdre des tests s'ils sont dans une arborescence distincte. Soyons honnêtes, tôt ou tard , vous vous retrouvez avec une structure de dossiers totalement différent, comme django , flacon et bien d' autres. Ce qui est bien si vous ne vous en souciez pas.
La principale question que vous devez vous poser est la suivante:
Suis-je en train d'écrire:
Si un:
Un dossier séparé et l'effort supplémentaire pour maintenir sa structure peuvent être mieux adaptés. Personne ne se plaindra du déploiement de vos tests en production .
Mais il est également tout aussi facile d'exclure les tests de la distribution lorsqu'ils sont mélangés aux dossiers principaux; mettez ceci dans le setup.py :
Si b:
Vous pouvez souhaiter - comme chacun de nous - que vous écriviez des bibliothèques réutilisables, mais la plupart du temps leur vie est liée à la vie du projet. La capacité de maintenir facilement votre projet devrait être une priorité.
Ensuite, si vous avez fait du bon travail et que votre module convient parfaitement à un autre projet, il sera probablement copié - non bifurqué ou transformé dans une bibliothèque distincte - dans ce nouveau projet, et déplacera les tests qui se trouvent à côté de lui dans la même structure de dossiers est facile par rapport à la recherche de tests dans un gâchis devenu un dossier de test séparé. (Vous pouvez affirmer que cela ne devrait pas être un gâchis en premier lieu, mais soyons réalistes ici).
Donc, le choix est toujours le vôtre, mais je dirais qu'avec des tests mixtes, vous réalisez les mêmes choses qu'avec un dossier séparé, mais avec moins d'efforts pour garder les choses en ordre.
la source
J'utilise un
tests/
répertoire, puis j'importe les principaux modules d'application à l'aide d'importations relatives. Donc, dans MyApp / tests / foo.py, il pourrait y avoir:pour importer le
MyApp.foo
module.la source
Je ne crois pas qu'il existe une "meilleure pratique" établie.
J'ai placé mes tests dans un autre répertoire en dehors du code de l'application. J'ajoute ensuite le répertoire principal de l'application à sys.path (vous permettant d'importer les modules de n'importe où) dans mon script de test runner (qui fait aussi d'autres choses) avant d'exécuter tous les tests. De cette façon, je n'ai jamais à supprimer le répertoire tests du code principal lorsque je le libère, ce qui me fait gagner du temps et des efforts, si infime.
la source
os.sys.path.append(os.dirname('..'))
D'après mon expérience dans le développement de frameworks de test en Python, je suggère de placer les tests unitaires python dans un répertoire séparé. Maintenez une structure de répertoire symétrique. Cela serait utile pour empaqueter uniquement les bibliothèques de base et non pour empaqueter les tests unitaires. Ci-dessous est implémenté à travers un diagramme schématique.
De cette façon, lorsque vous empaquetez ces bibliothèques à l'aide d'un rpm, vous pouvez simplement empaqueter les modules de bibliothèque principaux (uniquement). Cela facilite la maintenabilité, en particulier dans un environnement agile.
la source
Je vous recommande de vérifier certains des principaux projets Python sur GitHub et d'obtenir quelques idées.
Lorsque votre code s'agrandit et que vous ajoutez plus de bibliothèques, il est préférable de créer un dossier de test dans le même répertoire que vous avez setup.py et de refléter la structure de votre répertoire de projet pour chaque type de test (unittest, intégration, ...)
Par exemple, si vous avez une structure de répertoires comme:
Après avoir ajouté le dossier de test, vous aurez une structure de répertoires comme:
De nombreux packages Python correctement écrits utilisent la même structure. Un très bon exemple est le paquet Boto. Vérifiez https://github.com/boto/boto
la source
matplotlib
il a sousmatplotlib/lib/matplotlib/tests
( github.com/matplotlib/matplotlib/tree/… ),sklearn
il a sousscikitelearn/sklearn/tests
( github.com/scikit-learn/scikit-learn/tree/master/sklearn/tests )Comment je le fais ...
Structure des dossiers:
Setup.py pointe vers src / comme l'emplacement contenant mes modules de projets, puis je lance:
Ce qui ajoute mon projet dans des packages de site, pointant vers ma copie de travail. Pour exécuter mes tests, j'utilise:
En utilisant le testeur que j'ai configuré.
la source
code.py
. Il serait plus judicieux d'appeler le répertoire de premier niveau "projet".Je préfère le répertoire des tests de haut niveau. Cela signifie que les importations deviennent un peu plus difficiles. Pour cela j'ai deux solutions:
test_suite='tests.runalltests.suite'
danssetup()
, et peut exécuter les tests simplement:python setup.py test
PYTHONPATH=. python tests/runalltests.py
Voici comment ces éléments sont pris en charge par le code dans M2Crypto:
Si vous préférez exécuter des tests avec nosetests, vous devrez peut-être faire quelque chose d'un peu différent.
la source
Nous utilisons
Dans chaque fichier de test que nous insérons
../src/
danssys.path
. Ce n'est pas la meilleure solution mais ça marche. Je pense que ce serait génial si quelqu'un venait avec quelque chose comme maven en java qui vous donne des conventions standard qui fonctionnent, peu importe le projet sur lequel vous travaillez.la source
Si les tests sont simples, mettez-les simplement dans la docstring - la plupart des frameworks de test pour Python pourront utiliser cela:
Pour d'autres tests plus impliqués, je les mettrais dans
../tests/test_module.py
ou danstests/test_module.py
.la source
En C #, j'ai généralement séparé les tests dans un assemblage séparé.
En Python - jusqu'à présent - j'ai eu tendance à écrire des doctests, où le test se trouve dans la docstring d'une fonction, ou à les mettre dans le
if __name__ == "__main__"
bloc en bas du module.la source
Lors de l'écriture d'un package appelé "foo", je mettrai les tests unitaires dans un package séparé "foo_test". Les modules et sous-packages auront alors le même nom que le module de package SUT. Par exemple, les tests pour un module foo.xy se trouvent dans foo_test.xy Les fichiers __init__.py de chaque package de test contiennent alors une suite AllTests qui inclut toutes les suites de test du package. setuptools fournit un moyen pratique de spécifier le package de test principal, de sorte qu'après "développement de python setup.py", vous pouvez simplement utiliser "test de python setup.py" ou "python setup.py test -s foo_test.x.SomeTestSuite" dans le juste une suite spécifique.
la source
J'ai mis mes tests dans le même répertoire que le code sous test (CUT); pour
foo.py
les tests seront enfoo_ut.py
ou similaire. (Je modifie le processus de découverte de test pour les trouver.)Cela place les tests juste à côté du code dans une liste de répertoires, ce qui rend évident que les tests sont là et rend l'ouverture des tests aussi simple que possible lorsqu'ils sont dans un fichier séparé. (Pour les éditeurs de ligne de commande
vim foo*
et lorsque vous utilisez un navigateur de système de fichiers graphique, cliquez simplement sur le fichier CUT, puis sur le fichier de test immédiatement adjacent.)Comme d' autres l'ont souligné , cela facilite également la refactorisation et l'extraction du code pour une utilisation ailleurs si cela s'avère nécessaire.
Je n'aime vraiment pas l'idée de placer les tests dans une arborescence de répertoires complètement différente; pourquoi rendre plus difficile que nécessaire pour les développeurs d'ouvrir les tests lorsqu'ils ouvrent le fichier avec la CUT? Ce n'est pas comme si la grande majorité des développeurs sont si désireux d'écrire ou de peaufiner les tests qu'ils ignoreront tout obstacle à cela, au lieu d'utiliser la barrière comme excuse. (Bien au contraire, selon mon expérience; même lorsque vous faites en sorte que cela soit aussi simple que possible, je connais de nombreux développeurs qui ne peuvent pas se soucier d'écrire des tests.)
la source
J'ai récemment commencé à programmer en Python, donc je n'ai pas encore vraiment eu la chance de découvrir les meilleures pratiques. Mais, j'ai écrit un module qui va et trouve tous les tests et les exécute.
Donc j'ai:
Je vais devoir voir comment ça se passe au fur et à mesure que je progresse vers des projets plus importants.
la source