Di pytest, apa gunanya file conftest.py?

218

Saya baru-baru ini menemukan pytest. Sepertinya bagus. Namun, saya merasa dokumentasinya bisa lebih baik.

Saya mencoba memahami untuk apa conftest.pyfile-file itu digunakan.

Dalam suite tes saya (saat ini kecil) saya punya satu conftest.pyfile di root proyek. Saya menggunakannya untuk menentukan perlengkapan yang saya injeksi ke dalam tes saya.

Saya punya dua pertanyaan:

  1. Apakah ini penggunaan yang benar conftest.py? Apakah ada kegunaan lain?
  2. Bisakah saya memiliki lebih dari satu conftest.pyfile? Kapan saya ingin melakukan itu? Contoh akan dihargai.

Secara lebih umum, bagaimana Anda mendefinisikan tujuan dan penggunaan conftest.pyfile yang benar dalam test suite py.test?

Aviv Cohn
sumber
9
Anda memiliki saya diIt seems great. However, I feel the documentation could be better.
user9074332
7
Ya, dokumentasinya bisa jadi jauh lebih baik. Saya mencari seluruh dokumentasi pytest untuk conftest.pydan meskipun ada banyak referensi untuk melakukan hal ini atau melakukan hal itu dengan file conftest, tidak ada dalam dokumentasi yang pernah menunjukkan bahwa ketika pytest melakukan penemuan tes, semua file conftest.py ditemukan (di dalam direktori strucutre di mana penemuan tes sedang dilakukan) akan dijalankan selama fase pengumpulan tes (sebelum tes dijalankan). Harus mencari tahu sendiri melalui eksperimen.
Daniel Goldfarb

Jawaban:

290

Apakah ini penggunaan conftest.py yang benar?

Ya itu. Perlengkapan adalah potensi dan penggunaan umum conftest.py. Perlengkapan yang akan Anda tetapkan akan dibagikan di antara semua tes di ruang tes Anda. Namun, mendefinisikan fixture di root conftest.pymungkin tidak berguna dan itu akan memperlambat pengujian jika fixture tersebut tidak digunakan oleh semua tes.

Apakah ada kegunaan lain?

Ya itu.

  • Jadwal : Menentukan perlengkapan untuk data statis yang digunakan oleh tes. Data ini dapat diakses oleh semua tes di suite kecuali ditentukan lain. Ini bisa berupa data serta bantuan modul yang akan diteruskan ke semua tes.

  • Pemuatan plugin eksternal : conftest.pydigunakan untuk mengimpor plugin atau modul eksternal. Dengan mendefinisikan variabel global berikut, pytest akan memuat modul dan membuatnya tersedia untuk pengujian. Plugin umumnya file yang ditentukan dalam proyek Anda atau modul lain yang mungkin diperlukan dalam pengujian Anda. Anda juga dapat memuat satu set plugin yang telah ditentukan seperti dijelaskan di sini .

    pytest_plugins = "someapp.someplugin"

  • Kait : Anda dapat menentukan kait seperti metode pengaturan dan teardown dan banyak lagi untuk meningkatkan tes Anda. Untuk satu set kait yang tersedia, baca di sini . Contoh:

    def pytest_runtest_setup(item):
         """ called before ``pytest_runtest_call(item). """
         #do some stuff`
    
  • Test root path : Ini adalah fitur tersembunyi. Dengan mendefinisikan conftest.pypath root Anda, Anda akan pytestmengenali modul aplikasi Anda tanpa menentukan PYTHONPATH. Di latar belakang, py.test memodifikasi Anda sys.pathdengan memasukkan semua submodul yang ditemukan dari path root.

Bisakah saya memiliki lebih dari satu file conftest.py?

Ya, Anda bisa dan sangat disarankan jika struktur pengujian Anda agak rumit. conftest.pyfile memiliki cakupan direktori. Oleh karena itu, menciptakan perlengkapan dan penolong yang ditargetkan adalah praktik yang baik.

Kapan saya ingin melakukan itu? Contoh akan dihargai.

Beberapa kasus dapat ditampung:

Membuat seperangkat alat atau pengait untuk kelompok pengujian tertentu.

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"

Memuat satu set perlengkapan untuk beberapa tes tetapi tidak untuk yang lain.

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)

Akan mencetak "beberapa hal lain".

Override kait diwarisi dari akar 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

Dengan menjalankan tes apa pun di dalam root/mod, hanya "Saya mod" yang dicetak.

Anda dapat membaca lebih lanjut tentang di conftest.py sini .

EDIT:

Bagaimana jika saya membutuhkan fungsi helper lama yang dipanggil dari sejumlah tes dalam modul yang berbeda - akankah mereka tersedia bagi saya jika saya meletakkannya di conftest.py? Atau haruskah saya memasukkannya ke dalam modul helpers.py dan mengimpor dan menggunakannya dalam modul pengujian saya?

Anda dapat menggunakan conftest.pyuntuk menentukan pembantu Anda. Namun, Anda harus mengikuti praktik umum. Pembantu dapat digunakan sebagai perlengkapan setidaknya di pytest. Sebagai contoh dalam tes saya, saya memiliki pembantu redis mock yang saya menyuntikkan ke tes saya dengan cara ini.

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'))

Ini akan menjadi modul tes yang dapat Anda impor secara bebas dalam tes Anda. CATATAN bahwa Anda berpotensi memberi nama redis.pyseolah- conftest.pyolah modul Anda redisberisi lebih banyak tes. Namun, praktik itu tidak dianjurkan karena ambiguitas.

Jika Anda ingin menggunakannya conftest.py, Anda bisa memasukkan pembantu itu ke root conftest.pydan menyuntikkannya saat diperlukan.

root / tes / conftest.py

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

root / test / stuff / test.py

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

Hal lain yang dapat Anda lakukan adalah menulis plugin yang dapat diinstal. Dalam hal ini, pembantu Anda dapat ditulis di mana saja tetapi perlu menentukan titik masuk untuk dipasang di kerangka kerja Anda dan potensi pengujian lainnya. Lihat ini .

Jika Anda tidak ingin menggunakan perlengkapan, tentu saja Anda dapat menentukan pembantu sederhana dan cukup menggunakan impor lama polos di mana pun itu diperlukan.

root / tes / helper / redis.py

class MockRedis():
    # stuff

root / test / stuff / test.py

from helper.redis import MockRedis

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

Namun, di sini Anda mungkin memiliki masalah dengan jalur karena modul tidak ada dalam folder anak tes. Anda harus dapat mengatasi ini (tidak diuji) dengan menambahkan sebuah __init__.pyke pembantu Anda

root / test / helper / __ init__.py

from .redis import MockRedis

Atau cukup menambahkan modul pembantu ke PYTHONPATH.

Simone Zandara
sumber
saya menghadapi situasi di mana modul tes unit pertama saya, test_aaaaa.pysebenarnya mencoba untuk berjalan sebelum pengaturan fixture selesai conftest.py. Adakah pemikiran mengapa hal ini dapat terjadi?
user9074332
Tanpa conftest.py, jalur root pengujian Anda tidak dapat ditambahkan ke sys.path, dan Anda akan melihat kesalahan seperti "ModuleNotFoundError: Tidak ada modul bernama 'foobar'".
Cale Sweeney
11

Dalam arti luas conftest.py adalah plugin per-direktori lokal. Di sini Anda menentukan kait dan perlengkapan khusus direktori. Dalam kasus saya memiliki direktori root yang berisi direktori tes khusus proyek. Beberapa sihir umum ditempatkan di 'root' conftest.py. Khusus proyek - dalam proyek mereka sendiri. Tidak dapat melihat sesuatu yang buruk dalam menyimpan fixture di conftest.py kecuali mereka tidak digunakan secara luas (Dalam hal ini saya lebih suka mendefinisikannya dalam file tes secara langsung)

Bebek Furious
sumber
10

Saya menggunakan conftest.pyfile untuk menentukan perlengkapan yang saya suntikkan ke dalam tes saya, apakah ini penggunaan yang benar conftest.py?

Ya , fixture biasanya digunakan untuk mendapatkan data yang siap untuk beberapa tes.

Apakah ada kegunaan lain?

Ya , fixture adalah fungsi yang dijalankan pytestsebelum, dan kadang-kadang setelah, fungsi tes yang sebenarnya. Kode dalam fixture dapat melakukan apa pun yang Anda inginkan. Misalnya, fixture dapat digunakan untuk mendapatkan set data agar tes dapat dikerjakan, atau fixture juga dapat digunakan untuk membuat sistem menjadi kondisi yang diketahui sebelum menjalankan tes.

Bisakah saya memiliki lebih dari satu conftest.pyfile? Kapan saya ingin melakukan itu?

Pertama, dimungkinkan untuk menempatkan perlengkapan ke dalam file uji individual. Namun, untuk berbagi perlengkapan di antara beberapa file pengujian, Anda perlu menggunakan conftest.pyfile di suatu tempat yang terletak terpusat untuk semua tes. Jadwal dapat dibagi dengan tes apa pun. Mereka dapat dimasukkan ke dalam file tes individual jika Anda ingin fixture hanya digunakan oleh tes dalam file itu.

Kedua, ya , Anda dapat memiliki conftest.pyfile lain di subdirektori dari direktori tes teratas. Jika Anda melakukannya, perlengkapan yang ditentukan dalam conftest.pyfile - file tingkat rendah ini akan tersedia untuk pengujian dalam direktori dan subdirektori tersebut.

Akhirnya, menempatkan fixture dalam conftest.pyfile di root tes akan membuatnya tersedia di semua file uji.

lmiguelvargasf
sumber