Saya memiliki beberapa jenis data pengujian dan ingin membuat unit test untuk setiap item. Ide pertama saya adalah melakukannya seperti ini:
import unittest
l = [["foo", "a", "a",], ["bar", "a", "b"], ["lee", "b", "b"]]
class TestSequence(unittest.TestCase):
def testsample(self):
for name, a,b in l:
print "test", name
self.assertEqual(a,b)
if __name__ == '__main__':
unittest.main()
Kelemahan dari ini adalah bahwa ia menangani semua data dalam satu tes. Saya ingin membuat satu tes untuk setiap item dengan cepat. Ada saran?
python
unit-testing
parameterized-unit-test
Peter Hoffmann
sumber
sumber
Jawaban:
Ini disebut "parametrization".
Ada beberapa alat yang mendukung pendekatan ini. Misalnya:
Kode yang dihasilkan terlihat seperti ini:
Yang akan menghasilkan tes:
Untuk alasan historis, saya akan meninggalkan jawaban asli sekitar 2008):
Saya menggunakan sesuatu seperti ini:
sumber
.__name__ =
untuk mengaktifkan.exact_method
pengujianif __name__ == '__main__'
conditional? Tentunya itu harus keluar dari ini untuk berjalan pada waktu impor (mengingat bahwa modul python hanya diimpor sekali bahkan jika diimpor dari beberapa tempat yang berbeda)Menggunakan unittest (sejak 3.4)
Sejak Python 3.4,
unittest
paket perpustakaan standar memilikisubTest
manajer konteks.Lihat dokumentasi:
Contoh:
Anda juga dapat menentukan pesan khusus dan nilai parameter untuk
subTest()
:Menggunakan hidung
The hidung kerangka pengujian mendukung ini .
Contoh (kode di bawah ini adalah seluruh isi file yang berisi tes):
Output dari perintah nosetests:
sumber
Ini bisa diselesaikan dengan elegan menggunakan Metaclasses:
sumber
__new__
Metode dalam metaclass dipanggil saat kelas itu sendiri didefinisikan, bukan ketika instance pertama dibuat. Saya akan membayangkan metode ini menciptakan metode tes secara dinamis lebih kompatibel dengan introspeksi yang digunakan olehunittest
untuk menentukan berapa banyak tes di kelas (yaitu mungkin menyusun daftar tes sebelum pernah membuat turunan dari kelas itu).class TestSequence(unittest.TestCase, metaclass=TestSequenceMeta):[...]
dct
bukandict
? Menggunakan kata kunci sebagai nama variabel membingungkan dan rentan kesalahan.Pada Python 3.4 subtitle telah diperkenalkan ke unittest untuk tujuan ini. Lihat dokumentasi untuk detailnya. TestCase.subTest adalah manajer konteks yang memungkinkan seseorang untuk mengisolasi pernyataan dalam suatu pengujian sehingga kegagalan akan dilaporkan dengan informasi parameter tetapi tidak menghentikan pelaksanaan pengujian. Inilah contoh dari dokumentasi:
Output dari uji coba adalah:
Ini juga merupakan bagian dari unittest2 , sehingga tersedia untuk versi Python sebelumnya.
sumber
setUp()
dantearDown()
tidak berjalan di antara sub-tes.)self.setUp()
secara teori dapat dipanggil secara manual dari dalam subtest. AdapuntearDown
, memanggilnya secara otomatis di akhir mungkin sudah cukup.load_tests adalah mekanisme yang sedikit dikenal diperkenalkan pada 2.7 untuk secara dinamis membuat TestSuite. Dengan itu, Anda dapat dengan mudah membuat tes parametrized.
Sebagai contoh:
Kode itu akan menjalankan semua TestCases di TestSuite yang dikembalikan oleh load_tests. Tidak ada tes lain yang secara otomatis dijalankan oleh mekanisme penemuan.
Atau, Anda juga dapat menggunakan warisan seperti yang ditunjukkan dalam tiket ini: http://bugs.python.org/msg151444
sumber
Itu bisa dilakukan dengan menggunakan pytest . Cukup tulis file
test_me.py
dengan konten:Dan jalankan tes Anda dengan perintah
py.test --tb=short test_me.py
. Maka hasilnya akan terlihat seperti:Sederhana saja! Juga pytest memiliki lebih banyak fitur seperti
fixtures
,mark
,assert
, dll ...sumber
py.test
unittest
ke py.test. Saya dulu memilikiTestCase
kelas dasar yang mampu secara dinamis membuat anak-anak dengan argumen yang berbeda yang akan mereka simpan sebagai variabel kelas ... yang agak sulit digunakan.py.test
adalah yield_fixtures . Yang dapat melakukan pengaturan , mengembalikan beberapa data yang berguna ke dalam pengujian dan setelah tes berakhir membuat teardown . Perlengkapan juga dapat parametirized .Gunakan perpustakaan ddt . Ini menambahkan dekorator sederhana untuk metode pengujian:
Pustaka ini dapat diinstal dengan
pip
. Itu tidak memerlukannose
, dan bekerja sangat baik denganunittest
modul perpustakaan standar .sumber
Anda akan mendapat manfaat dari mencoba perpustakaan TestScenarios .
sumber
Ada juga Hipotesis yang menambahkan pengujian berbasis properti atau fuzz: https://pypi.python.org/pypi/hypothesis
Ini adalah metode pengujian yang sangat kuat.
sumber
@given()
makro di dalam kelas unittest.Anda dapat menggunakan plugin nose-ittr (
pip install nose-ittr
).Sangat mudah untuk diintegrasikan dengan tes yang ada, perubahan minimal (jika ada) diperlukan. Ini juga mendukung plugin multi-pemrosesan hidung .
Bukan berarti Anda juga dapat memiliki
setup
fungsi penyesuaian per pengujian.Dimungkinkan juga untuk melewatkan
nosetest
parameter seperti dengan plugin bawaannyaattrib
, dengan cara ini Anda hanya dapat menjalankan tes khusus dengan parameter tertentu:sumber
Saya menggunakan metaclasses dan dekorator untuk menghasilkan tes. Anda dapat memeriksa implementasi python_wrap_cases saya . Perpustakaan ini tidak memerlukan kerangka uji apa pun.
Contoh Anda:
Output konsol:
Anda juga dapat menggunakan generator . Misalnya kode ini menghasilkan semua kemungkinan kombinasi pengujian dengan argumen
a__list
danb__list
Output konsol:
sumber
Saya menemukan ParamUnittest tempo hari ketika melihat kode sumber ke radon ( contoh penggunaan pada repo github ). Ini harus bekerja dengan kerangka kerja lain yang memperpanjang TestCase (seperti Hidung).
Berikut ini sebuah contoh:
sumber
HASIL:
sumber
def add_test_methods
fungsi Anda . Seharusnyadef _add_test_methods
saya pikirCukup gunakan metaclasses, seperti yang terlihat di sini;
Keluaran:
sumber
Anda dapat menggunakan
TestSuite
dan mengkustomisasiTestCase
kelas.sumber
__init__
fungsi.Saya telah menemukan bahwa ini bekerja dengan baik untuk tujuan saya, terutama jika saya perlu membuat tes yang melakukan sedikit perbedaan proses pada kumpulan data.
The
TestGenerator
kelas dapat digunakan untuk bertelur set yang berbeda dari uji kasus sepertiTestCluster
.TestCluster
dapat dianggap sebagai implementasi dariTestGenerator
antarmuka.sumber
Solusi ini berfungsi dengan
unittest
dannose
untuk Python 2 dan Python 3:sumber
Saya mengalami masalah dengan gaya pengujian parameter yang sangat khusus. Semua tes Selenium kami dapat berjalan secara lokal, tetapi tes tersebut juga harus dapat dijalankan dari jarak jauh terhadap beberapa platform di SauceLabs. Pada dasarnya, saya ingin mengambil sejumlah besar test case yang sudah ditulis dan parameter mereka dengan perubahan kode sesedikit mungkin. Selain itu, saya harus dapat melewatkan parameter ke dalam metode setUp, sesuatu yang saya belum melihat solusi untuk tempat lain.
Inilah yang saya buat:
Dengan ini, yang harus saya lakukan adalah menambahkan dekorator sederhana @sauce_labs () ke setiap TestCase lama yang biasa, dan sekarang ketika menjalankannya, mereka dibungkus dan ditulis ulang, sehingga semua metode pengujian diparameterisasi dan diganti nama. LoginTests.test_login (self) berjalan sebagai LoginTests.test_login_internet_explorer_10.0 (self), LoginTests.test_login_internet_explorer_11.0 (self), dan LoginTests.test_login_firefox_43.0 (self), dan masing-masing memiliki browser untuk menentukan sendiri parameter apa saja / parameter apa saja yang menentukan sendiri parameternya. platform untuk melawan, bahkan di LoginTests.setUp, yang sangat penting untuk tugas saya karena di situlah koneksi ke SauceLabs diinisialisasi.
Bagaimanapun, saya harap ini bisa membantu seseorang yang ingin melakukan parameterisasi "global" yang serupa dari tes mereka!
sumber
Jawaban berbasis metaclass masih berfungsi di Python3, tetapi alih-alih
__metaclass__
atribut yang harus digunakanmetaclass
parameter, seperti pada:sumber
Pemrograman meta memang menyenangkan, tetapi bisa digunakan. Sebagian besar solusi di sini mempersulit:
Jadi, saran pertama saya adalah mengikuti jalur sederhana / eksplisit (berfungsi dengan semua test runner):
Karena kita tidak boleh mengulangi sendiri, saran kedua saya didasarkan pada jawaban @ Javier: merangkul pengujian berbasis properti. Perpustakaan hipotesis:
memiliki banyak fitur menarik lainnya (statistik, output tes tambahan, ...)
kelas TestSequence (unittest.TestCase):
Untuk menguji contoh spesifik Anda, cukup tambahkan:
Untuk menjalankan hanya satu contoh tertentu, Anda dapat mengomentari contoh-contoh lain (contoh yang diberikan akan dijalankan terlebih dahulu). Anda mungkin ingin menggunakan
@given(st.nothing())
. Pilihan lain adalah mengganti seluruh blok dengan:Oke, Anda tidak memiliki nama tes yang berbeda. Tapi mungkin Anda hanya perlu:
Contoh yang lebih lucu
sumber
Sangat terlambat ke pesta, tapi aku kesulitan membuat ini berhasil
setUpClass
.Inilah versi jawaban @ Javier yang memberikan
setUpClass
akses ke atribut yang dialokasikan secara dinamis.Keluaran
sumber
Hanya untuk melempar solusi lain ke dalam campuran;)
Ini secara efektif sama
parameterized
dengan yang disebutkan di atas, tetapi khusus untukunittest
:Contoh penggunaan:
sumber
Selain menggunakan setattr, kita dapat menggunakan load_tests sejak python 3.2. Silakan merujuk ke posting blog blog.livreuro.com/en/coding/python/how-to-generate-discoverable-unit-tests-in-python-dynamically/
sumber
Berikut ini adalah solusi saya. Saya menemukan ini berguna ketika: 1. Harus bekerja untuk unittest.Testcase dan unittest temukan 2. Memiliki serangkaian tes yang akan dijalankan untuk pengaturan parameter yang berbeda. 3. Sangat sederhana tidak ada ketergantungan pada impor paket lain unittest
sumber
sumber