2017-10-17 12 views
2

J'utilise Py.Test pour tester des fonctions dans une application Python Flask.PyTest échoue sur un répertoire avec plusieurs fichiers de test lors de la modularisation des appareils

J'ai les tests qui passent bien lorsque j'utilise un fichier "app_test.py" qui contient tous les appareils et tests. Maintenant que j'ai divisé les projecteurs dans leur propre module, et séparé les tests en différents modules qui importent chacun le module d'appareils, je rencontre des problèmes.

Si je lance des tests sur chaque module individuellement, tout passe bien: pytest tests/test_1.py, pytest tests/test_2.py, pytest tests/test_3.py, etc. Mais les ennuis commencent si je veux exécuter tous les tests dans l'ordre avec une seule commande, par exemple pytest tests.

je reçois le premier module de tests de passage et tous les futurs signaler une erreur:

AssertionError: A setup function was called after the first request was handled. 
This usually indicates a bug in the application where a module was not imported 
and decorators or other functionality was called too late. 
E To fix this make sure to import all your view modules, database models 
and everything related at a central place before the application starts 
serving requests. 

Tous les tests et les appareils dans un seul fichier ressemble à ceci:

# app_test.py 

from flask_app import create_app 
@pytest.fixtures(scope="session") 
def app(request): 
    app = create_app() 
    with app.app_context(): 
     yield app 

@pytest.fixture(scope="session"): 
def client(request, app): 
    client = app.test_client() 
    return client 


def test1(client): 
    # test body 

def test2(client): 
    # test body 

... 

Je cours $ pytest app_test.py et tout fonctionne parfaitement. Maintenant, disons que nous les divisons en trois modules différents: fixures.py, test_1.py et test_2.py. Le code ressemble maintenant à ceci.

# tests/fixtures.py 
from flask_app import create_app 
@pytest.fixtures(scope="session") 
def app(request): 
    app = create_app() 
    with app.app_context(): 
     yield app 

@pytest.fixture(scope="session"): 
def client(request, app): 
    client = app.test_client() 
    return client 

# tests/test_1.py 
from tests.fixtures import app, client 
def test_1(client): 
    # test body 

# tests/test_2.py 
from tests.fixtures import app, client 
def test_2(client): 
    # test body 

Si nous courons $ pytest tests alors les tests/test_1.py passera, et les tests/test_2.py soulèvera l'erreur.

J'ai regardé ce gist, et j'ai essayé de marquer les fonctions de test avec @pytest.mark.usefixture sans succès. Comment exécuter Py.Test avec des appareils modularisés sur un répertoire qui contient plusieurs fichiers de test?

+0

S'il vous plaît [modifier] pour inclure un [mcve], y compris la pleine retraçage. Comme le message d'erreur indique, vous avez fait quelque chose à l'application après avoir traité une demande. Cela implique qu'un test, ou une fonction dans l'application, a modifié l'application. Tu n'es pas censé faire ça. Mais encore une fois, nous avons besoin d'un [mcve] pour savoir ce qui ne va pas. – davidism

+0

@davidism Merci pour votre commentaire. Je n'ai pas réussi à créer un MCV qui reproduisait l'erreur (j'obtiendrais une fonction de vue mappant AssertionError au lieu de l'erreur ci-dessus). En postant j'espérais que j'avais une erreur conceptuelle que quelqu'un avec plus d'expérience que moi avec pytest identifierait – ABM

Répondre

2

Vous utilisez les appareils légèrement incorrectement. En particulier, vous déclarez plusieurs projecteurs du même nom et avec le même objet-fonction, mais détectés sur différents modules. Du point de vue de pytest, ceux-ci devraient être les fonctions séparées, parce que pytest fait dir(module) pour détecter les tests & appareils dans le dossier. Mais d'une manière ou d'une autre à cause de la même fonction-objet, je pense, pytest se souvient d'eux comme étant les mêmes; donc une fois que vous arrivez au deuxième fichier de test, il essaye le nom du fixture détecté localement, mais le trouve déjà préparé et échoue.

L'utilisation correcte serait de créer un pseudo-plugin conftest.py, et y mettre tous les appareils. Une fois déclarés, ces appareils seront disponibles pour tous les fichiers de ce répertoire et tous les sous-répertoires.

Remarque: ces appareils ne doivent PAS être importés dans les fichiers de test. Les appareils ne sont pas les fonctions. Pytest les prépare automatiquement et les nourrit aux tests.

# tests/conftest.py 
import pytest 
from flask_app import create_app 

@pytest.fixtures(scope="session") 
def app(request): 
    app = create_app() 
    with app.app_context(): 
     yield app 

@pytest.fixture(scope="session"): 
def client(request, app): 
    client = app.test_client() 
    return client 

Et les fichiers de test (notez l'absence des importations!):

# tests/test_1.py 
def test_1(client): 
    # test body 

# tests/test_2.py 
def test_2(client): 
    # test body 

Voir plus: https://docs.pytest.org/en/latest/writing_plugins.html