web-dev-qa-db-fra.com

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

J'écris des tests Selenium, avec un ensemble de classes, chaque classe contenant plusieurs tests. Chaque classe ouvre et ferme actuellement 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 ...
  • se bloque, car après la fermeture de firefox, essayer de le rouvrir très rapidement, à partir de Selenium, entraîne une "erreur 54"

Je pourrais résoudre l'erreur 54, probablement, en ajoutant un sommeil, mais ce serait quand même super lent.

Donc, ce que j'aimerais faire, c'est réutiliser les mêmes instances de Firefox dans 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.

36
Hugh Perkins

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

# content of conftest.py or a tests file (e.g. in your tests or root directory)

@pytest.fixture(scope="session", autouse=True)
def do_something(request):
    # prepare something ahead of all tests
    request.addfinalizer(finalizer_function)

Cela se déroulera avant tous les tests. Le finaliseur sera appelé une fois le dernier test terminé.

46
hpk42

L'utilisation du fixture de session comme suggéré par hpk42 est une excellente solution dans de nombreux cas, mais le fixture ne fonctionnera qu'après la collecte de tous les tests.

Voici deux autres solutions:

crochets conftest

Écrire un pytest_configure ou pytest_sessionstart accrocher votre conftest.py fichier:

# content of conftest.py


def pytest_configure(config):
    """
    Allows plugins and conftest files to perform initial configuration.
    This hook is called for every plugin and initial conftest
    file after command line options have been parsed.
    """


def pytest_sessionstart(session):
    """
    Called after the Session object has been created and
    before performing collection and entering the run test loop.
    """


def pytest_sessionfinish(session, exitstatus):
    """
    Called after whole test run finished, right before
    returning the exit status to the system.
    """


def pytest_unconfigure(config):
    """
    called before test process is exited.
    """

plugin pytest

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

# content of conftest.py

pytest_plugins = [
    'plugins.example_plugin',
]


# content of plugins/example_plugin.py
def pytest_configure(config):
    pass


def pytest_unconfigure(config):
    pass
52
draganHR

À partir de la version 2.10, il existe un moyen plus propre de démonter le luminaire et de définir sa portée. Vous pouvez donc utiliser cette syntaxe:

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

Le paramètre autouse: De documentation :

Voici comment fonctionnent les appareils autouse dans d'autres étendues:

  • les luminaires autouse obéissent à l'argument mot-clé scope =: si un luminaire autouse a scope = 'session', il ne sera exécuté qu'une seule fois, peu importe où il est défini. scope = 'class' signifie qu'il sera exécuté une fois par classe, etc.

  • si un appareil autouse est défini dans un module de test, toutes ses fonctions de test l'utilisent automatiquement.

  • si un appareil autouse est défini dans un fichier conftest.py, alors tous les tests de tous les modules de test sous son répertoire invoqueront l'appareil.

    ...

Le paramètre "request": Notez que le paramètre "request" n'est pas nécessaire pour votre objectif bien que vous souhaitiez l'utiliser à d'autres fins. De documentation :

"La fonction Fixture peut accepter l'objet de demande pour introspecter la fonction de test" demandeuse ", le contexte de classe ou de module."

16
Pavel Rogovoy