115 votes

Comment exécuter une méthode avant tous les tests dans toutes les classes?

Je suis en train d'écrire des tests selenium, avec un ensemble de classes, chaque classe contenant plusieurs tests. Chaque classe ouvre actuellement puis ferme Firefox, ce qui a deux conséquences:

  • super lent, l'ouverture de firefox prend plus de temps que l'exécution du test dans une classe...
  • plante, car après avoir fermé firefox, essayer de le rouvrir rapidement, depuis selenium, entraîne une 'Erreur 54'

Je pourrais résoudre l'erreur 54, probablement, en ajoutant un délai, mais cela resterait très lent.

Donc, ce que j'aimerais faire, c'est réutiliser les mêmes instances de Firefox à travers toutes les classes de test. Ce qui signifie que je dois exécuter une méthode avant toutes les classes de test, et une autre méthode après toutes les classes de test. Ainsi, 'setup_class' et 'teardown_class' ne sont pas suffisants.

145voto

draganHR Points 392

Utiliser l'élément de configuration de session tel que suggéré par hpk42 est une excellente solution pour de nombreux cas, mais la configuration ne s'exécutera qu'après la collecte de tous les tests.

Voici deux autres solutions :

hooks de conftest

Écrivez un hook pytest_configure ou pytest_sessionstart dans votre fichier conftest.py (voir où placer le fichier conftest.py ici)

# contenu de conftest.py

def pytest_configure(config):
    """
    Permet aux plugins et aux fichiers de configuration initiale d'effectuer une configuration initiale.
    Ce hook est appelé pour chaque plugin et fichier de configuration initiale après que les options de ligne de commande aient été analysées.
    """

def pytest_sessionstart(session):
    """
    Appelé après la création de l'objet Session et avant de réaliser la collecte et d'entrer dans la boucle de test.
    """

def pytest_sessionfinish(session, exitstatus):
    """
    Appelé après la fin de l'exécution de tous les tests, juste avant
    de retourner le statut de sortie au système.
    """

def pytest_unconfigure(config):
    """
    Appelé avant la sortie du processus de test.
    """

plugin pytest

Créez un plugin pytest avec les hooks pytest_configure et pytest_unconfigure.
Activez votre plugin dans conftest.py:

# contenu de conftest.py

pytest_plugins = [
    'plugins.example_plugin',
]

# contenu de plugins/example_plugin.py
def pytest_configure(config):
    pass

def pytest_unconfigure(config):
    pass

109voto

hpk42 Points 3494

Vous voudrez peut-être utiliser un fixture "autouse" à portée de session :

# contenu de conftest.py ou d'un fichier de tests (par exemple, dans vos tests ou votre répertoire racine)

@pytest.fixture(scope="session", autouse=True)
def do_something(request):
    # préparer quelque chose avant tous les tests
    request.addfinalizer(finalizer_function)

Ceci s'exécutera avant tous les tests. Le finalizer sera appelé après que le dernier test soit terminé.

42voto

Pavel Rogovoy Points 408

À partir de la version 2.10, il existe une manière plus propre de démanteler le fixture ainsi que de définir sa portée. Vous pouvez donc utiliser cette syntaxe :

@pytest.fixture(scope="module", autouse=True)
def my_fixture():
    print('INITIALISATION')
    yield param
    print('DESTRUCTION')

Le paramètre autouse : D'après la documentation :

Voici comment les fixtures autouse fonctionnent dans d'autres portées :

  • Les fixtures autouse respectent l'argument de portée « scope= » : si une fixture autouse a une portée 'session', elle ne sera exécutée qu'une seule fois, peu importe où elle est définie. La portée 'classe' signifie qu'elle sera exécutée une fois par classe, etc.

  • Si une fixture autouse est définie dans un module de test, toutes ses fonctions de test l'utilisent automatiquement.

  • Si une fixture autouse est définie dans un fichier conftest.py, alors tous les tests dans tous les modules de test situés en dessous de son répertoire invoqueront la fixture.

...

Le paramètre "request" : Notez que le paramètre "request" n'est pas nécessaire pour votre objectif, bien que vous puissiez l'utiliser à d'autres fins. D'après la documentation :

"La fonction de fixture peut accepter l'objet request pour inspecter le contexte de la fonction de test, de la classe ou du module qui fait la demande."

15voto

Nikita Romanov Points 101

Essayez d'utiliser pytest_sessionstart(session) dans conftest.py

Exemple:

# project/tests/conftest.py

def pytest_sessionstart(session):
    print('AVANT')

# project/tests/tests_example/test_sessionstart.py

import pytest

@pytest.fixture(scope='module', autouse=True)
def fixture():
    print('FIXTURE')

def test_sessonstart():
    print('TEST')

Journal:

AVANT
============================================================================ démarrage de la session de test =============================================================================
plateforme darwin -- Python 3.7.0, pytest-5.4.1, py-1.8.1, pluggy-0.13.1 -- /Library/Frameworks/Python.framework/Versions/3.7/bin/python3
cachedir: .pytest_cache
rootdir: /Users/user/Documents/test, inifile: pytest.ini
plugins: allure-pytest-2.8.12, env-0.6.2
collecté 1 élément                                                                                                                                                             

tests/6.1/test_sessionstart.py::test_sessonstart FIXTURE
TEST
PASSED

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X