Di bidang pengujian otomatis, Anda dapat menemukan alat yang berbeda, misalnya, py.test adalah salah satu solusi paling populer untuk menulis tes otomatis dengan Python.
Setelah melalui banyak sumber daya yang terkait dengan pytest dan setelah mempelajari dokumentasi dari situs resmi proyek, saya tidak dapat menemukan deskripsi langsung dari solusi untuk salah satu tugas utama - menjalankan tes dengan data uji yang disimpan dalam file terpisah. Kalau tidak, dapat dikatakan, pemuatan parameter ke dalam fungsi uji dari file (s) atau parameterisasi dari file secara langsung. Prosedur seperti itu tidak dijelaskan di mana saja dalam seluk-beluk dan satu-satunya penyebutan fitur ini hanya dalam satu baris dari dokumentasi pytest.
Pada artikel ini saya akan berbicara tentang solusi saya untuk masalah ini.
Tantangan
Tugas utama adalah untuk menghasilkan kasus uji dalam bentuk parameter test_input
dan expected_result
ke masing-masing fungsi tes individu dari nama fungsi file yang sesuai.
Tugas tambahan:
- pilih format file yang dapat dibaca manusia dengan kasus uji;
- meninggalkan kemampuan untuk mendukung kasus uji hard-coded;
- menampilkan pengidentifikasi yang jelas untuk setiap kasus.
Toolkit
Dalam artikel tersebut, saya menggunakan Python 3 (2.7 juga cocok), pyyaml, dan pytest
(versi 5+ untuk Python 3, atau 4.6 untuk Python 2.7) tanpa menggunakan plugin pihak ketiga. Selain itu, pustaka os
standar akan digunakan.
File itu sendiri dari mana kita akan mengambil kasus uji perlu disusun menggunakan bahasa markup yang nyaman bagi pemahaman manusia. Dalam kasus saya, YAML dipilih (karena itu menyelesaikan tugas tambahan memilih format yang dapat dibaca manusia) . Bahkan, bahasa markup seperti apa untuk file dengan set data yang Anda butuhkan tergantung pada persyaratan yang disajikan pada proyek.
Implementasi
Karena pilar utama alam semesta dalam pemrograman adalah kesepakatan, kita harus memperkenalkan beberapa darinya untuk solusi kita.
Intersepsi
Untuk mulai dengan, solusi ini menggunakan fungsi intersepsi pytest_generate_tests
( wiki ), yang dimulai pada tahap menghasilkan kasus uji, dan metafunc
argumennya, yang memungkinkan kita untuk parameterisasi fungsi. Pada titik ini, pytest mengulangi setiap fungsi tes dan menjalankan kode generasi selanjutnya untuk itu.
Argumen
Anda harus menentukan daftar lengkap parameter untuk fungsi tes. Dalam kasus saya, kamusnya adalah test_input
dan semua tipe data (paling sering berupa string atau integer) dalam expected_result
. Kami membutuhkan parameter ini untuk digunakan di metafunc.parametrize(...)
.
Parameterisasi
Fungsi ini sepenuhnya mengulangi operasi @pytest.mark.parametrize
parameterisasi @pytest.mark.parametrize
, yang mengambil argumen pertama string yang mencantumkan argumen fungsi pengujian (dalam kasus kami "test_input, expected_result"
) dan daftar data yang akan digunakan untuk membuat kasus pengujian kami (misalnya, [(1, 2), (2, 4), (3, 6)]
)).
Dalam pertempuran, akan terlihat seperti ini:
@pytest.mark.parametrize("test_input, expected_result", [(1, 2), (2, 4), (3, 6)]) def test_multiplication(test_input, expected_result): assert test_input * 2 == expected_result
Dan dalam kasus kami, kami akan menunjukkan ini sebelumnya:
Penyaringan
Dari sini juga mengikuti alokasi fungsi-fungsi tes di mana data dari file diperlukan, dari mereka yang menggunakan data statis / dinamis. Kami akan menerapkan penyaringan ini sebelum mengurai informasi dari file.
Filter itu sendiri bisa berupa apa saja, misalnya:
- Penanda fungsi bernama
yaml
:
Jika tidak, filter yang sama dapat diterapkan seperti ini:
- Argumen ke fungsi
test_input
:
Opsi ini paling cocok untuk saya.
Hasil
Kita hanya perlu menambahkan bagian di mana kita mengurai data dari file. Ini tidak akan sulit dalam kasus yaml (dan juga json, xml, dll.) , Jadi kami mengumpulkan semuanya ke heap.
Kami menulis skrip pengujian seperti ini:
File data:
# test_multiplication.yaml - !!python/tuple [1,2] - !!python/tuple [1,3] - !!python/tuple [1,5] - !!python/tuple [2,4] - !!python/tuple [3,4] - !!python/tuple [5,4]
Kami mendapatkan daftar kasus uji berikut:
pytest /test_script.py --collect-only ======================== test session starts ======================== platform linux -- Python 3.7.4, pytest-5.2.1, py-1.8.0, pluggy-0.13.0 rootdir: /pytest_habr collected 6 items <Module test_script.py> <Function test_multiplication[1-2]> <Function test_multiplication[1-3]> <Function test_multiplication[1-5]> <Function test_multiplication[2-4]> <Function test_multiplication[3-4]> <Function test_multiplication[5-4]> ======================== no tests ran in 0.04s ========================
Dan dengan menjalankan skrip, hasil ini: 4 failed, 2 passed, 1 warnings in 0.11s
Tambah. tugas
Ini bisa menjadi akhir artikel, tetapi untuk kompleksitas yang lebih besar, saya akan menambahkan pengidentifikasi yang lebih nyaman untuk fungsi kita, data lain yang menguraikan dan menandai setiap kasus uji individu.
Jadi, segera, kode:
Karenanya, kami mengubah tampilan file YAML kami:
# test_multiplication.yaml - test_data: [1, 2] id: 'one_two' - test_data: [1,3] marks: ['xfail'] - test_data: [1,5] marks: ['skip'] - test_data: [2,4] id: "it's good" marks: ['xfail'] - test_data: [3,4] marks: ['negative'] - test_data: [5,4] marks: ['more_than']
Maka uraian akan berubah menjadi:
<Module test_script.py> <Function test_multiplication[one_two]> <Function test_multiplication[1_3]> <Function test_multiplication[1_5]> <Function test_multiplication[it's good]> <Function test_multiplication[3_4]> <Function test_multiplication[5_4]>
Dan peluncurannya adalah: 2 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 2 warnings in 0.12s
PS: peringatan - karena spidol yang ditulis sendiri tidak dicatat di pytest.ini
Dalam pengembangan topik
Siap untuk berdiskusi di komentar pertanyaan tentang jenis:
- apa cara terbaik untuk menulis file yaml?
- Dalam format apa lebih nyaman menyimpan data uji?
- Kasus uji tambahan apa yang dibutuhkan pada tahap pembuatan?
- Apakah saya perlu pengidentifikasi untuk setiap kasus?