Perlengkapan Pytest
Fixtures adalah fungsi pembantu pytest yang digunakan untuk membuat pengujian modular, dapat diskalakan, dan mudah dipelihara. Anda menggunakan perlengkapan untuk menyiapkan prasyarat untuk pengujian seperti koneksi database, membuat data pengujian, atau mengonfigurasi status sistem yang diperlukan sebelum pengujian dapat berjalan. Mereka juga dapat digunakan untuk pembersihan setelah pengujian selesai berjalan.
Karakteristik utama dari perlengkapan pytest meliputi:
-
Kontrol cakupan: Perlengkapan dapat dikonfigurasi untuk memiliki cakupan yang berbeda menggunakan
scopeparameter (sepertifunction, ,classmodule, atausession), yang menentukan seberapa sering perlengkapan dipanggil. - Penanganan penyiapan dan pembongkaran: Pytest mengelola siklus hidup fixture, secara otomatis menyiapkan dan membongkar sesuai kebutuhan.
- Injeksi dependensi: Perlengkapan disuntikkan ke dalam fungsi pengujian sebagai argumen, sehingga jelas pengujian mana yang mengandalkan perlengkapan mana.
- Penggunaan kembali dan modularitas: Perlengkapan dapat didefinisikan di satu tempat dan digunakan di beberapa fungsi pengujian, modul, atau bahkan proyek.
Membuat pengaturan file sementara
Saat menulis pengujian yang berinteraksi dengan file, umumnya memerlukan file sementara yang tidak mengacaukan sistem file pasca-pengujian. Dengan pytest, kita dapat membuat fixture yang menyiapkan file sementara. Perlengkapan ini menggunakan modul tempfile Python untuk menghasilkan file sementara dengan aman, memastikan bahwa mereka dapat digunakan dan dihapus tanpa memengaruhi lingkungan lokal. (Pada versi awal konfigurasi kami ini, file tidak akan dihapus secara otomatis karena tanda delete=False. Kami akan menangani penghapusan file nanti.)
Berikut tampilan perlengkapannya:
import pytest
import tempfile
@pytest.fixture
def tmp_file():
def create():
# Create a named temporary file that persists beyond the function scope
temp = tempfile.NamedTemporaryFile(delete=False)
return temp.name
return create
Dalam pengaturan ini, tmp_file() bertindak sebagai alat penyangga. Nama perlengkapan adalah cara pengujian merujuknya. Dalam fixture, fungsi bersarang create() membuat file hanya ketika dipanggil, bukan saat penyiapan fixture. Ini memungkinkan kontrol yang tepat ketika file sementara dibuat, yang berguna dalam pengujian di mana waktu dan status file sangat penting.
Dalam fungsi berlapis create(), file sementara dibuat lalu mengembalikan jalur absolut ke dalamnya. Berikut adalah contoh bagaimana suatu tes mungkin menggunakan pengaturan yang telah kami buat:
import os
def test_file(tmp_file):
path = tmp_file()
assert os.path.exists(path)
Pengujian menggunakan perlengkapan dengan menentukan nama perlengkapan sebagai argumen. Kasus penggunaan sederhana kami dapat dengan mudah diperluas dengan menulis ke file atau membuat modifikasi seperti mengubah izin atau kepemilikan.
Manajemen cakupan
Dalam pytest, mengelola siklus hidup sumber daya pengujian melalui pengaturan dan rutinitas teardown sangat penting untuk mempertahankan lingkungan pengujian yang bersih dan efisien. Anda juga ingin melindungi integritas pengujian dengan memastikan bahwa setiap pengujian dimulai dengan status yang diketahui dan konsisten. Secara default, perlengkapan pytest beroperasi dengan cakupan function, yang memengaruhi perilaku dengan dua cara:
- Siklus hidup per pengujian: Nilai pengembalian perlengkapan dihitung ulang untuk setiap fungsi pengujian yang menggunakannya, memastikan bahwa setiap pengujian beroperasi dengan status baru.
- Pembersihan setelah setiap penggunaan: Setiap operasi pembersihan yang diperlukan dilakukan setelah setiap pengujian yang menggunakan perlengkapan.
Pytest juga memungkinkan perlengkapan untuk dilingkup lebih luas untuk mengoptimalkan performa dan penggunaan sumber daya. Cakupan sangat berguna dalam situasi seperti mengelola status database atau ketika Anda memiliki penyiapan status kompleks yang memakan waktu untuk dibuat. Empat cakupan yang tersedia adalah:
-
function: Cakupan default, perlengkapan dijalankan sekali per pengujian -
class: Konfigurasi dijalankan sekali per kelas pengujian. -
module: Dijalankan sekali untuk satu modul. -
session: Dijalankan sekali per sesi pengujian. Cakupan ini berguna untuk operasi mahal yang perlu bertahan di seluruh sesi pengujian, seperti menginisialisasi layanan atau memulai server database.
Dalam hal ini, berjalan sekali berarti bahwa nilai kembalian disimpan dalam cache. Jadi perlengkapan yang memiliki cakupan "modul" dapat dipanggil beberapa kali dalam modul pengujian, tetapi nilai yang dikembalikan adalah dari pengujian pertama yang memanggilnya.
Berikut tampilan perlengkapan tmp_file() dengan cakupan modul:
import pytest
import tempfile
@pytest.fixture(scope="module")
def tmp_file():
def create():
temp = tempfile.NamedTemporaryFile(delete=False)
return temp.name
return create
Manajemen pembersihan
Kode sebelumnya yang mengatur konfigurasi tmp_file membuat file sementara, tetapi tidak secara otomatis menangani penghapusan setelah pengujian selesai. Untuk memastikan bahwa file sementara tidak tertinggal, Anda dapat menggunakan fixture request pytest untuk mendaftarkan fungsi pembersihan.
Berikut cara mengubah perlengkapan tmp_file untuk menyertakan pembersihan otomatis:
import pytest
import tempfile
import os
@pytest.fixture(scope="module")
def tmp_file(request):
# Create a temporary file that persists beyond the function scope
temp = tempfile.NamedTemporaryFile(delete=False)
def create():
# Returns the path of the temporary file
return temp.name
def cleanup():
# Remove the file after the tests are done
os.remove(temp.name)
# Register the cleanup function to be called after the last test in the module
request.addfinalizer(cleanup)
return create
Dengan menggunakan request.addfinalizer() dan meneruskan fungsi bertingkat cleanup(), pembersihan akan dipanggil berdasarkan cakupannya. Dalam hal ini, cakupannya adalah module, jadi setelah semua pengujian dalam modul, pytest akan memanggil fungsi pembersihan tersebut.
Menggunakan conftest.py
Alih-alih menyertakan perlengkapan Anda dalam file pengujian, Anda dapat menyimpannya dalam file conftest.py . Semua perlengkapan dalam conftest.py secara otomatis tersedia untuk pengujian Anda di direktori yang sama tanpa harus mengimpornya secara eksplisit.
Menjelajahi perangkat bawaan
Pytest memiliki banyak perlengkapan bawaan yang dirancang untuk menyederhanakan pengujian. Perlengkapan ini dapat menangani penyiapan dan pembersihan secara otomatis, memungkinkan Anda untuk fokus menulis kasus pengujian Anda alih-alih manajemen pengujian.
Perlengkapan bawaan utama meliputi:
-
cache: Digunakan untuk membuat dan mengelola cache tingkat pengujian, yang berguna untuk menyimpan data di antara sesi pengujian. -
capsys: Menangkap dan memungkinkan inspeksistderrdanstdout, sehingga memudahkan untuk memeriksa dan menguji output konsol. -
tmpdir: Menyediakan direktori sementara untuk file yang perlu dibuat dan digunakan selama pengujian. -
monkeypatch: Menyediakan cara untuk memodifikasi perilaku dan nilai objek, fungsi, dan lingkungan os Anda dengan aman.
Peran monkeypatching dalam pengujian
Menguji kode yang terintegrasi erat dengan sumber daya eksternal seperti database atau API eksternal dapat menjadi tantangan karena dependensi yang terlibat. Teknik yang disebut monkey patching melibatkan modifikasi sementara sistem Anda selama uji coba, sehingga Anda dapat independen dari sistem eksternal dan dapat mengubah status serta perilaku lingkungan sistem operasi Anda dengan aman selama proses pengujian.
Berikut adalah contoh cara mengambil alih fungsi os.path.exists() menggunakan fikstur monkeypatch:
import os
def test_os(monkeypatch):
# Override os.path.exists to always return False
monkeypatch.setattr('os.path.exists', lambda x: False)
assert not os.path.exists('/')
Atau, Anda dapat menggunakan metode setattr() dengan referensi langsung ke objek dan atribut:
def test_os(monkeypatch):
# Specify the object and attribute to override
monkeypatch.setattr(os.path, 'exists', lambda x: False)
assert not os.path.exists('/')
Selain mengatur atribut dan mengambil alih metode, perlengkapan monkeypatch dapat mengatur dan menghapus variabel lingkungan, mengubah nilai kamus, dan memodifikasi jalur sistem. Perangkat monkeypatch secara otomatis mengembalikan perubahan apa pun setelah setiap pengujian, tetapi kehati-hatian tetap harus diperhatikan saat menggunakan perangkat monkeypatch. Berikut adalah beberapa alasan untuk berhati-hati saat menggunakannya:
-
Kejelasan dan pemeliharaan kode: Terlalu banyak menggunakannya monkeypatch dengan cara yang kompleks dapat membuat pengujian lebih sulit dipahami dan dirawat. Ketika Anda membaca hasil pengujian, mungkin tidak langsung jelas bagaimana perilaku komponen seharusnya dalam kondisi normal dibandingkan dengan saat mereka dimodifikasi untuk pengujian.
-
Validitas pengujian: Monkeypatching terkadang dapat menyebabkan pengujian yang lulus dalam kondisi buatan yang sangat berbeda dari lingkungan produksi. Ini dapat menciptakan rasa keamanan yang salah, karena pengujian mungkin lulus karena pengujian mengubah perilaku sistem terlalu dramatis.
-
Ketergantungan berlebihan pada detail implementasi: Pengujian yang mengandalkan monkeypatching mungkin terkait erat dengan detail implementasi tertentu dari kode yang mereka uji. Ini dapat membuat tes rapuh dan rentan terhadap pemecahan dengan perubahan kecil pada basis kode yang mendasar.
-
Kompleksitas penelusuran kesalahan: Penelusuran kesalahan pengujian yang menggunakan monkeypatch bisa lebih kompleks, terutama jika patch mengubah aspek mendasar dari perilaku aplikasi. Memahami mengapa pengujian gagal mungkin memerlukan penyelaman yang lebih dalam tentang bagaimana komponen dimodifikasi selama pengujian.
Meskipun monkeypatch adalah alat yang kuat untuk membuat lingkungan pengujian yang terisolasi dan terkontrol, itu harus digunakan secara yudisial dan dengan pemahaman yang jelas tentang bagaimana hal itu memengaruhi rangkaian pengujian dan perilaku aplikasi.