108 votes

Comment contrôler l'ordre d'exécution des cas de test dans pytest ?

J'ai deux fichiers dans un répertoire. Dans l'un des fichiers, il y a un cas de test de longue durée qui génère une certaine sortie. Dans l'autre fichier, il y a un cas de test qui lit cette sortie.

Comment puis-je garantir l'ordre d'exécution correct des deux cas de test? Y a-t-il une autre alternative que de mettre les cas de test dans le même fichier dans le bon ordre?

103voto

Frank T Points 649

En général, vous pouvez configurer le comportement de pratiquement n'importe quelle partie de pytest en utilisant ses hooks bien spécifiés.

Dans votre cas, vous voulez le hook "pytest_collection_modifyitems", qui vous permet de réorganiser les tests collectés sur place.

Cela dit, il semble que l'ordonnancement de vos tests devrait être plus facile - après tout, c'est du Python! J'ai donc écrit un plugin pour ordonner les tests: "pytest-ordering". Consultez la documentation ou installez-la depuis pypi. Pour l'instant, je recommande d'utiliser @pytest.mark.first et @pytest.mark.second, ou l'un des marqueurs @pytest.mark.order#, mais j'ai quelques idées sur des APIs plus utiles. Les suggestions sont les bienvenues :)

Édition: pytest-ordering semble abandonné pour le moment, vous pouvez également consulter pytest-order (un fork du projet original par l'auteur).

Édition2: Dans pytest-order, seul un marqueur (order) est pris en charge, et les exemples mentionnés seraient @pytest.mark.order("first"), @pytest.mark.order("second"), ou @pytest.mark.order(#) (avec # étant un nombre quelconque).

35voto

asterio gonzalez Points 300

Peut-être que vous pouvez envisager d'utiliser le plugin pytest dependency, où vous pouvez facilement définir les dépendances entre les tests.

Soyez prudent - les commentaires suggèrent que cela ne fonctionne pas pour tout le monde.

@pytest.mark.dependency()
def test_long():
    pass

@pytest.mark.dependency(depends=['test_long'])
def test_short():
    pass

Ainsi, test_short s'exécutera uniquement si test_long réussit et forcera également la séquence d'exécution.

16voto

Ignacio Points 105

Comme indiqué par @Frank T dans la réponse acceptée, le pytest_collection_modifyitems accroche permet de modifier l'ordre des tests collectés (items) sur place. Cette approche a l'avantage de ne pas nécessiter de bibliothèque tierce.

Un exemple complet sur la façon d'imposer l'ordre d'exécution des cas de test par classe de test est déjà disponible dans cette réponse.

Dans ce cas, cependant, il semble que vous voudriez imposer l'ordre d'exécution par module de test (c'est-à-dire, le fichier .py où se trouve le test). L'adaptation suivante vous permettrait de le faire:

#conftest.py
def pytest_collection_modifyitems(items):
    """Modifie les éléments de test sur place pour garantir que les modules de test s'exécutent dans un ordre donné."""
    MODULE_ORDER = ["tests.test_b", "tests.test_c", "tests.test_a"]
    module_mapping = {item: item.module.__name__ for item in items}

    sorted_items = items.copy()
    # Déplacer itérativement les tests de chaque module à la fin de la file d'attente des tests
    for module in MODULE_ORDER:
        sorted_items = [it for it in sorted_items if module_mapping[it] != module] + [
            it for it in sorted_items if module_mapping[it] == module
        ]
    items[:] = sorted_items

Placer l'extrait ci-dessus dans conftest.py remplace l'ordre d'exécution des tests alphabétique par défaut test_a -> test_b -> test_c par test_b -> test_c -> test_a. Les modules peuvent être dans différents sous-répertoires de test, et l'ordre des tests à l'intérieur d'un module reste inchangé.

11voto

Ali Zwd Points 87

Les fixtures de Pytest peuvent être utilisées pour ordonner les tests de manière similaire à la façon dont elles ordonnent la création des fixtures. Bien que cela soit inhabituel, cela tire parti des connaissances que vous pourriez déjà avoir sur le système de fixtures, cela ne nécessite pas de package séparé et est peu probable d'être modifié par des plugins pytest.

@pytest.fixture(scope='session')
def test_A():
    pass

@pytest.mark.usefixtures('test_A')
def test_B():
    pass

La portée empêche de faire plusieurs appels à test_A s'il y a plusieurs tests qui en dépendent.

6voto

funky-future Points 36

Il existe également un plugin pytest-ordering qui semble répondre à vos besoins.

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