web-dev-qa-db-fra.com

Dans pytest, à quoi servent les fichiers conftest.py?

J'ai récemment découvert pytest. Cela semble génial. Cependant, je pense que la documentation pourrait être meilleure.

J'essaie de comprendre à quoi servent les fichiers conftest.py.

Dans ma (actuellement petite) suite de tests, j'ai un fichier conftest.py à la racine du projet. Je l'utilise pour définir les fixtures que j'injecte dans mes tests.

J'ai deux questions:

  1. Est-ce l'utilisation correcte de conftest.py? At-il d'autres utilisations?
  2. Puis-je avoir plus d'un fichier conftest.py? Quand voudrais-je faire cela? Des exemples seront appréciés.

Plus généralement, comment définiriez-vous l'objectif et l'utilisation correcte du ou des fichiers conftest.py dans une suite de tests py.test?

152
Aviv Cohn

Est-ce l'utilisation correcte de conftest.py?

Oui, ça l'est. Les appareils constituent une utilisation potentielle et courante de conftest.py. Les appareils que vous définissez seront partagés entre tous les tests de votre suite de tests. Cependant, définir des fixtures dans la racine conftest.py pourrait être inutile et ralentirait les tests si de telles fixtures ne sont pas utilisées par tous les tests.

At-il d'autres utilisations?

Oui.

  • Fixtures : définissez les fixtures pour les données statiques utilisées par les tests. Tous les tests de la suite peuvent accéder à ces données, sauf indication contraire. Cela pourrait être des données ainsi que des aides de modules qui seront passés à tous les tests.

  • Chargement de plug-in externe : conftest.py est utilisé pour importer des plug-ins ou des modules externes. En définissant la variable globale suivante, pytest chargera le module et le rendra disponible pour son test. Les plugins sont généralement des fichiers définis dans votre projet ou d'autres modules pouvant être nécessaires à vos tests. Vous pouvez également charger un ensemble de plugins prédéfinis comme expliqué ici .

    pytest_plugins = "someapp.someplugin"

  • Crochets : Vous pouvez spécifier des crochets tels que des méthodes d'installation et de démontage et bien plus encore pour améliorer vos tests. Pour un ensemble d'hameçons disponibles, lisez ici . Exemple:

    def pytest_runtest_setup(item):
         """ called before ``pytest_runtest_call(item). """
         #do some stuff`
    
  • Testez le chemin racine : il s’agit d’un élément caché. En définissant conftest.py dans votre chemin racine, vous aurez pytest reconnaître vos modules d'application sans spécifier PYTHONPATH. En arrière-plan, py.test modifie votre sys.path en incluant tous les sous-modules trouvés à partir du chemin racine.

Puis-je avoir plus d'un fichier conftest.py?

Oui, vous le pouvez et cela est vivement recommandé si votre structure de test est quelque peu complexe. Les fichiers conftest.py ont une portée de répertoire. Par conséquent, créer des fixtures et des aides ciblés est une bonne pratique.

Quand est-ce que je voudrais faire ça? Des exemples seront appréciés.

Plusieurs cas pourraient convenir:

Création d'un ensemble d'outils ou de crochets pour un groupe de tests particulier.

root/mod/conftest.py

def pytest_runtest_setup(item):
    print("I am mod")
    #do some stuff


test root/mod2/test.py will NOT produce "I am mod"

Chargement d'un ensemble de fixtures pour certains tests mais pas pour d'autres.

root/mod/conftest.py

@pytest.fixture()
def fixture():
    return "some stuff"

root/mod2/conftest.py

@pytest.fixture()
def fixture():
    return "some other stuff"

root/mod2/test.py

def test(fixture):
    print(fixture)

Imprimera "d'autres choses".

Remplacement des crochets hérités de la racine conftest.py.

root/mod/conftest.py

def pytest_runtest_setup(item):
    print("I am mod")
    #do some stuff

root/conftest.py

def pytest_runtest_setup(item):
    print("I am root")
    #do some stuff

En exécutant un test dans root/mod, seul "je suis mod" est imprimé.

Vous pouvez en savoir plus sur conftest.pyhere .

EDIT:

Que se passe-t-il si des fonctions d’aide simples et anciennes doivent être appelées à partir d’un certain nombre de tests de différents modules - seront-elles disponibles si je les mets dans un conftest.py? Ou devrais-je simplement les mettre dans un module helpers.py, les importer et les utiliser dans mes modules de test?

Vous pouvez utiliser conftest.py pour définir vos assistants. Cependant, vous devriez suivre la pratique courante. Les helpers peuvent être utilisés comme fixtures au moins dans pytest. Par exemple, dans mes tests, j'ai un assistant fictif que j'injecte dans mes tests de cette façon.

root/helper/redis/redis.py

@pytest.fixture
def mock_redis():
    return MockRedis()

root/tests/stuff/conftest.py

pytest_plugin="helper.redis.redis"

root/tests/stuff/test.py

def test(mock_redis):
    print(mock_redis.get('stuff'))

Ce sera un module de test que vous pourrez importer librement dans vos tests. NOTEZ que vous pourriez potentiellement nommer redis.py comme conftest.py si votre module redis contient davantage de tests. Cependant, cette pratique est découragée en raison de l'ambiguïté.

Si vous voulez utiliser conftest.py, vous pouvez simplement mettre cette aide dans votre racine conftest.py et l'injecter si nécessaire.

root/tests/conftest.py

@pytest.fixture
def mock_redis():
    return MockRedis()

root/tests/stuff/test.py

def test(mock_redis):
    print(mock_redis.get(stuff))

Une autre chose que vous pouvez faire est d'écrire un plugin installable. Dans ce cas, votre assistant peut être écrit n'importe où, mais il doit définir un point d'entrée à installer dans votre infrastructure de test et dans d'autres. Voir this .

Si vous ne voulez pas utiliser de fixtures, vous pouvez bien sûr définir une simple aide et simplement utiliser la vieille importation simple, là où vous en avez besoin.

root/tests/helper/redis.py

class MockRedis():
    # stuff

root/tests/stuff/test.py

from helper.redis import MockRedis

def test():
    print(MockRedis().get(stuff))

Cependant, vous pourriez avoir des problèmes avec le chemin puisque le module ne se trouve pas dans un dossier enfant du test. Vous devriez pouvoir surmonter ceci (non testé) en ajoutant un __init__.py à votre aide.

racine/tests/aide/__ init __. py

from .redis import MockRedis

Ou simplement ajouter le module d'assistance à votre PYTHONPATH.

204
Simone Zandara

Au sens large, conftest.py est un plugin local par répertoire. Ici, vous définissez les hooks et les fixtures spécifiques à un répertoire. Dans mon cas, un répertoire racine contenant des répertoires de tests spécifiques au projet. Une certaine magie courante se trouve dans 'root' conftest.py. Spécifique au projet - dans leurs propres. Vous ne pouvez rien voir de mauvais en stockant les fixtures dans conftest.py à moins qu’ils ne soient pas largement utilisés (dans ce cas, je préfère les définir directement dans les fichiers de test)

10
Furious Duck

J'utilise le fichier conftest.py pour définir les fixtures que j'injecte dans mes tests. S'agit-il de l'utilisation correcte de conftest.py?

Yes, un appareil est généralement utilisé pour préparer les données à de multiples tests.

At-il d'autres utilisations?

Yes, un appareil est une fonction gérée par pytest avant et parfois après les fonctions de test réelles. Le code dans l'appareil peut faire ce que vous voulez. Par exemple, un appareil peut être utilisé pour obtenir un ensemble de données sur lequel les tests doivent fonctionner, ou peut également être utilisé pour obtenir un système dans un état connu avant d'exécuter un test.

Puis-je avoir plus d'un fichier conftest.py? Quand est-ce que je voudrais faire ça?

Premièrement, il est possible de placer des fixtures dans des fichiers de test individuels. Toutefois, pour partager des appareils entre plusieurs fichiers de test, vous devez utiliser un fichier conftest.py situé dans un emplacement central pour tous les tests. Les calendriers peuvent être partagés par tous les tests. Ils peuvent être placés dans des fichiers de test individuels si vous voulez que l'appareil ne soit utilisé que par les tests de ce fichier.

Deuxièmement, oui, vous pouvez avoir d’autres fichiers conftest.py dans les sous-répertoires du répertoire top tests. Si vous le faites, les fixtures définies dans ces fichiers conftest.py de niveau inférieur seront disponibles pour des tests dans ce répertoire et ces sous-répertoires.

Enfin, placer des fixtures dans le fichier conftest.py à la racine du test les rendra disponibles dans tous les fichiers de test.

6
lmiguelvargasf