W pytest, do czego służą pliki conftest.py?

217

Niedawno odkryłem pytest. Wygląda świetnie. Wydaje mi się jednak, że dokumentacja mogłaby być lepsza.

Próbuję zrozumieć, do jakich conftest.pyplików mają być używane.

W moim (obecnie małym) pakiecie testowym mam jeden conftest.pyplik w katalogu głównym projektu. Używam go do definiowania urządzeń, które wprowadzam do moich testów.

Mam dwa pytania:

  1. Czy to prawidłowe użycie conftest.py? Czy ma inne zastosowania?
  2. Czy mogę mieć więcej niż jeden conftest.pyplik? Kiedy chciałbym to zrobić? Przykłady będą mile widziane.

Mówiąc bardziej ogólnie, w jaki sposób zdefiniowałbyś cel i poprawne wykorzystanie conftest.pyplików w pakiecie testowym py.test?

Aviv Cohn
źródło
9
Miałeś mnie naIt seems great. However, I feel the documentation could be better.
user9074332,
7
Tak, dokumentacja mogłaby być o wiele lepsza. Przeszukałem całą dokumentację pytest w poszukiwaniu conftest.pyi chociaż istnieje wiele odniesień do robienia tego lub robienia tego z plikiem poufnym, nigdzie w dokumentacji nigdzie nie wskazuje, że kiedy pytest wykonuje testowe wykrywanie, znaleziono wszystkie pliki conftest.py (w katalog strucutre, nad którym odbywa się wykrywanie testu) zostanie uruchomiony podczas fazy zbierania testów (przed uruchomieniem jakichkolwiek testów). Musiałem to odkryć poprzez eksperymenty.
Daniel Goldfarb

Odpowiedzi:

288

Czy to prawidłowe użycie pliku conftest.py?

Tak to jest. Oprawy są potencjalnym i powszechnym zastosowaniem conftest.py. Urządzenia, które zdefiniujesz, będą współużytkowane przez wszystkie testy w twoim zestawie testów. Jednak zdefiniowanie urządzeń w katalogu głównym conftest.pymoże być bezużyteczne i spowolniłoby testowanie, gdyby takie urządzenia nie były używane we wszystkich testach.

Czy ma inne zastosowania?

Tak.

  • Urządzenia : Zdefiniuj urządzenia dla danych statycznych używanych przez testy. Dostęp do tych danych mają wszystkie testy w pakiecie, chyba że określono inaczej. Mogą to być zarówno dane, jak i moduły pomocnicze, które zostaną przekazane do wszystkich testów.

  • Ładowanie zewnętrznych wtyczek : conftest.pysłuży do importowania zewnętrznych wtyczek lub modułów. Poprzez zdefiniowanie następującej zmiennej globalnej, pytest załaduje moduł i udostępni go do testu. Wtyczki to na ogół pliki zdefiniowane w projekcie lub inne moduły, które mogą być potrzebne w testach. Możesz również załadować zestaw predefiniowanych wtyczek, jak wyjaśniono tutaj .

    pytest_plugins = "someapp.someplugin"

  • Haki : możesz określić haki, takie jak metody konfiguracji i porzucenia i wiele więcej, aby poprawić swoje testy. Zestaw dostępnych haczyków znajdziesz tutaj . Przykład:

    def pytest_runtest_setup(item):
         """ called before ``pytest_runtest_call(item). """
         #do some stuff`
  • Testuj ścieżkę katalogu głównego : jest to trochę ukryta funkcja. Po zdefiniowaniu conftest.pyw ścieżce katalogu głównego będziesz pytestrozpoznawał moduły aplikacji bez określania PYTHONPATH. W tle py.test modyfikuje twoje sys.path, włączając wszystkie podmoduły znalezione ze ścieżki root.

Czy mogę mieć więcej niż jeden plik conftest.py?

Tak, możesz i jest to zdecydowanie zalecane, jeśli twoja struktura testu jest nieco złożona. conftest.pypliki mają zasięg katalogu. Dlatego tworzenie ukierunkowanych urządzeń i pomocników jest dobrą praktyką.

Kiedy chciałbym to zrobić? Przykłady będą mile widziane.

Kilka skrzynek może pasować:

Tworzenie zestawu narzędzi lub haków dla określonej grupy testów.

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

Ładowanie zestawu urządzeń dla niektórych testów, ale nie dla innych.

root / mod / conftest.py

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

root / mod2 / conftest.py

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

root / mod2 / test.py

def test(fixture):
    print(fixture)

Wydrukuje „jakieś inne rzeczy”.

Przesłanianie haków odziedziczonych z katalogu głównego conftest.py.

root / mod / conftest.py

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

root / conftest.py

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

Po uruchomieniu dowolnego testu w środku root/moddrukowane jest tylko „Jestem modem”.

Możesz przeczytać więcej o conftest.py tutaj .

EDYTOWAĆ:

Co się stanie, jeśli będę potrzebować zwykłych funkcji pomocniczych do wywołania z szeregu testów w różnych modułach - czy będą one dla mnie dostępne, jeśli umieszczę je w pliku conftest.py? Czy powinienem po prostu umieścić je w module helpers.py oraz zaimportować i użyć w moich modułach testowych?

Możesz użyć conftest.pydo zdefiniowania swoich pomocników. Powinieneś jednak przestrzegać powszechnej praktyki. Pomocników można używać jako urządzeń przynajmniej w pytest. Na przykład w moich testach mam fałszywego pomocnika redis, który w ten sposób wstrzykuję do moich testów.

root / helper / redis / redis.py

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

root / testy / stuff / conftest.py

pytest_plugin="helper.redis.redis"

root / testy / stuff / test.py

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

Będzie to moduł testowy, który możesz swobodnie importować w swoich testach. UWAGA: możesz potencjalnie nazwać redis.pytak, conftest.pyjakby Twój moduł rediszawierał więcej testów. Praktyka ta jest jednak odradzana z powodu niejasności.

Jeśli chcesz użyć conftest.py, możesz po prostu umieścić pomocnika w swoim katalogu głównym conftest.pyi wstrzyknąć go w razie potrzeby.

root / testy / conftest.py

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

root / testy / stuff / test.py

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

Inną rzeczą, którą możesz zrobić, jest napisanie instalowalnej wtyczki. W takim przypadku pomocnik może zostać napisany w dowolnym miejscu, ale musi zdefiniować punkt wejścia do zainstalowania w twoim i innych potencjalnych ramach testowych. Zobacz to .

Jeśli nie chcesz używać urządzeń, możesz oczywiście zdefiniować prostego pomocnika i po prostu użyć zwykłego starego importu tam, gdzie jest to potrzebne.

root / testy / helper / redis.py

class MockRedis():
    # stuff

root / testy / stuff / test.py

from helper.redis import MockRedis

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

Jednak tutaj mogą występować problemy ze ścieżką, ponieważ moduł nie znajduje się w folderze podrzędnym testu. Powinieneś być w stanie pokonać to (nie przetestowane), dodając __init__.pydo swojego pomocnika

root / testy / pomocnik / __ init__.py

from .redis import MockRedis

Lub po prostu dodając moduł pomocnika do swojego PYTHONPATH.

Simone Zandara
źródło
napotykam sytuację, w której mój pierwszy moduł testu jednostkowego test_aaaaa.pypróbuje uruchomić się przed zakończeniem konfiguracji urządzenia conftest.py. Czy są jakieś przemyślenia, dlaczego tak się dzieje?
user9074332
Bez pliku conftest.py ścieżka testowego katalogu głównego nie zostanie dodana do ścieżki sys.path i zobaczysz błędy takie jak „ModuleNotFoundError: Brak modułu o nazwie„ foobar ””.
Cale Sweeney
11

W szerokim znaczeniu conftest.py to lokalna wtyczka dla poszczególnych katalogów. Tutaj definiujesz specyficzne dla katalogu zaczepy i urządzenia. W moim przypadku mam katalog główny zawierający katalogi testów specyficznych dla projektu. Pewna powszechna magia znajduje się w pliku „root” conftest.py. Specyficzne dla projektu - we własnych. Nie widzę nic złego w przechowywaniu urządzeń w conftest.py, chyba że nie są one powszechnie używane (w takim przypadku wolę zdefiniować je bezpośrednio w plikach testowych)

Furious Duck
źródło
10

Używam tego conftest.pypliku do definiowania urządzeń, które wprowadzam do moich testów, czy to właściwe użycie conftest.py?

Tak , urządzenie zwykle służy do przygotowania danych do wielu testów.

Czy ma inne zastosowania?

Tak , urządzenie to funkcja uruchamiana pytestprzed, a czasem po rzeczywistych funkcjach testowych. Kod w urządzeniu może robić, co chcesz. Na przykład, urządzenie może być użyte do uzyskania zestawu danych do testów, lub urządzenie może być również użyte do wprowadzenia systemu do znanego stanu przed uruchomieniem testu.

Czy mogę mieć więcej niż jeden conftest.pyplik? Kiedy chciałbym to zrobić?

Po pierwsze, możliwe jest umieszczenie urządzeń w poszczególnych plikach testowych. Aby jednak udostępnić urządzenia wielu plikom testowym, musisz użyć conftest.pypliku gdzieś centralnie zlokalizowanego dla wszystkich testów. Urządzenia mogą być współużytkowane przez dowolny test. Można je umieścić w osobnych plikach testowych, jeśli chcesz, aby urządzenie było używane tylko przez testy w tym pliku.

Po drugie, tak , możesz mieć inne conftest.pypliki w podkatalogach katalogu najlepszych testów. Jeśli to zrobisz, urządzenia zdefiniowane w tych conftest.pyplikach niższego poziomu będą dostępne do testów w tym katalogu i podkatalogach.

Wreszcie umieszczenie urządzeń w conftest.pypliku w testowym katalogu głównym spowoduje, że będą one dostępne we wszystkich plikach testowych.

lmiguelvargasf
źródło