In pytest, a che cosa servono i file conftest.py?


218

L'ho scoperto di recente pytest. Sembra fantastico Tuttavia, ritengo che la documentazione potrebbe essere migliore.

Sto cercando di capire a cosa conftest.pyservono i file.

Nella mia (attualmente piccola) suite di test ho un conftest.pyfile nella radice del progetto. Lo uso per definire i dispositivi che inserisco nei miei test.

Ho due domande:

  1. È questo l'uso corretto di conftest.py? Ha altri usi?
  2. Posso avere più di un conftest.pyfile? Quando vorrei farlo? Gli esempi saranno apprezzati.

Più in generale, come definiresti lo scopo e l'uso corretto dei conftest.pyfile in una suite di test py.test?


9
Mi avevi suIt seems great. However, I feel the documentation could be better.
user9074332

7
Sì, la documentazione potrebbe essere molto migliore. Ho cercato l'intera documentazione di Pytest per conftest.pye sebbene ci siano molti riferimenti a fare questa cosa o fare quella cosa con un file conftest, nessuna parte della documentazione indica mai che quando pytest verifica la scoperta, tutti i file conftest.py trovati (all'interno del la struttura di directory su cui viene eseguito il rilevamento dei test) verrà eseguita durante la fase di raccolta dei test (prima che vengano eseguiti eventuali test). Ho dovuto capirlo da solo attraverso la sperimentazione.
Daniel Goldfarb,

Risposte:


290

È questo l'uso corretto di conftest.py?

Sì. Le partite sono un uso potenziale e comune di conftest.py. I dispositivi che definirai verranno condivisi tra tutti i test nella tua suite di test. Tuttavia, la definizione di dispositivi nella radice conftest.pypotrebbe essere inutile e rallenterebbe i test se tali dispositivi non fossero utilizzati da tutti i test.

Ha altri usi?

Sì lo fa.

  • Dispositivi : definire dispositivi per i dati statici utilizzati dai test. È possibile accedere a questi dati da tutti i test nella suite se non diversamente specificato. Questi potrebbero essere dati e aiutanti di moduli che verranno passati a tutti i test.

  • Caricamento plug-in esterno : conftest.pyviene utilizzato per importare plug-in o moduli esterni. Definendo la seguente variabile globale, pytest caricherà il modulo e lo renderà disponibile per il suo test. I plug-in sono generalmente file definiti nel progetto o in altri moduli che potrebbero essere necessari nei test. Puoi anche caricare un set di plugin predefiniti come spiegato qui .

    pytest_plugins = "someapp.someplugin"

  • Hook : è possibile specificare hook come i metodi di installazione e smontaggio e molto altro per migliorare i test. Per un set di ganci disponibili, leggi qui . Esempio:

    def pytest_runtest_setup(item):
         """ called before ``pytest_runtest_call(item). """
         #do some stuff`
  • Test percorso root : questa è una caratteristica nascosta. Definendo conftest.pynel percorso di root, sarà necessario pytestriconoscere i moduli dell'applicazione senza specificare PYTHONPATH. In background, py.test modifica il tuo sys.pathincludendo tutti i sottomoduli che si trovano dal percorso di root.

Posso avere più di un file conftest.py?

Sì, è possibile ed è fortemente raccomandato se la struttura del test è alquanto complessa. conftest.pyi file hanno ambito di directory. Pertanto, creare infissi e aiutanti mirati è una buona pratica.

Quando vorrei farlo? Gli esempi saranno apprezzati.

Diversi casi potrebbero adattarsi:

Creazione di un set di strumenti o ganci per un particolare gruppo di test.

radice / 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"

Caricamento di una serie di dispositivi per alcuni test ma non per altri.

radice / mod / conftest.py

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

radice / mod2 / conftest.py

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

radice / mod2 / test.py

def test(fixture):
    print(fixture)

Stampa "alcune altre cose".

Override degli hook ereditati dalla radice conftest.py.

radice / mod / conftest.py

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

radice / conftest.py

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

Eseguendo qualsiasi test all'interno root/mod, viene stampato solo "I am mod".

Puoi leggere di più conftest.py qui .

MODIFICARE:

E se avessi bisogno di chiamare funzioni di supporto semplici da una serie di test in diversi moduli: saranno disponibili per me se le inserissi in conftest.py? O dovrei semplicemente metterli in un modulo helpers.py e importarli e usarli nei miei moduli di test?

Puoi usare conftest.pyper definire i tuoi aiutanti. Tuttavia, dovresti seguire la pratica comune. Gli helper possono essere utilizzati come dispositivi almeno in pytest. Ad esempio nei miei test ho un finto aiutante redis che inietto nei miei test in questo modo.

root / helper / Redis / redis.py

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

root / test / stuff / conftest.py

pytest_plugin="helper.redis.redis"

root / test / stuff / test.py

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

Questo sarà un modulo di test che puoi importare liberamente nei tuoi test. NOTA che potresti potenzialmente nominare redis.pycome conftest.pyse il tuo modulo rediscontenga più test. Tuttavia, tale pratica è scoraggiata a causa dell'ambiguità.

Se vuoi usare conftest.py, puoi semplicemente mettere quell'helper nella tua radice conftest.pye iniettarlo quando necessario.

root / test / conftest.py

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

root / test / stuff / test.py

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

Un'altra cosa che puoi fare è scrivere un plugin installabile. In tal caso il tuo helper può essere scritto ovunque ma deve definire un punto di ingresso da installare nel tuo e in altri potenziali framework di test. Vedere questo .

Se non si desidera utilizzare gli apparecchi, è possibile ovviamente definire un semplice aiuto e utilizzare semplicemente la vecchia importazione ovunque sia necessaria.

root / test / helper / redis.py

class MockRedis():
    # stuff

root / test / stuff / test.py

from helper.redis import MockRedis

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

Tuttavia, qui potresti avere problemi con il percorso poiché il modulo non si trova in una cartella figlio del test. Dovresti essere in grado di superarlo (non testato) aggiungendo un __init__.pyaiuto

root / test / helper / __ init__.py

from .redis import MockRedis

O semplicemente aggiungendo il modulo helper al tuo PYTHONPATH.


sto incontrando una situazione in cui il mio primo modulo di test dell'unità, in test_aaaaa.pyrealtà sta tentando di funzionare prima che la configurazione del dispositivo sia completata conftest.py. Qualche idea sul perché ciò possa accadere?
user9074332

Senza conftest.py, il percorso della radice del test non viene aggiunto a sys.path e vedrai errori come "ModuleNotFoundError: nessun modulo chiamato 'foobar'".
Cale Sweeney,

11

In un ampio senso conftest.py è un plug-in locale per directory. Qui si definiscono hook e dispositivi specifici della directory. Nel mio caso ho una directory root contenente directory di test specifiche del progetto. Qualche magia comune è di stanza in 'root' conftest.py. Progetto specifico - nei propri. Non riesco a vedere nulla di male nella memorizzazione di dispositivi in ​​conftest.py a meno che non siano ampiamente utilizzati (in tal caso preferisco definirli direttamente nei file di test)


10

Uso il conftest.pyfile per definire i dispositivi che inserisco nei miei test, è questo l'uso corretto conftest.py?

, di solito viene utilizzato un dispositivo per preparare i dati per più test.

Ha altri usi?

, un dispositivo è una funzione che viene eseguita pytestprima e talvolta dopo le funzioni di test effettive. Il codice nell'apparecchio può fare quello che vuoi. Ad esempio, un dispositivo può essere utilizzato per ottenere un set di dati su cui lavorare i test oppure un dispositivo per portare un sistema in uno stato noto prima di eseguire un test.

Posso avere più di un conftest.pyfile? Quando vorrei farlo?

Innanzitutto, è possibile inserire dispositivi in ​​singoli file di test. Tuttavia, per condividere i dispositivi tra più file di test, è necessario utilizzare un conftest.pyfile posizionato centralmente per tutti i test. Le partite possono essere condivise da qualsiasi test. Possono essere inseriti in singoli file di test se si desidera che l'apparecchiatura venga utilizzata solo dai test in quel file.

In secondo luogo, , puoi avere altri conftest.pyfile nelle sottodirectory della directory dei test principali. In tal caso, i dispositivi definiti in questi conftest.pyfile di livello inferiore saranno disponibili per i test in quella directory e sottodirectory.

Infine, inserendo gli infissi nel conftest.pyfile nella radice del test li renderanno disponibili in tutti i file di test.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.