Jika Anda menulis perpustakaan, atau aplikasi, ke mana file tes unit ini pergi?
Sangat bagus untuk memisahkan file uji dari kode aplikasi utama, tetapi canggung untuk menempatkannya dalam subdirektori "tes" di dalam direktori root aplikasi, karena akan lebih sulit untuk mengimpor modul yang akan Anda uji.
Apakah ada praktik terbaik di sini?
python
unit-testing
code-organization
Hanya baca
sumber
sumber
Jawaban:
Untuk file
module.py
, tes unit biasanya dipanggiltest_module.py
, mengikuti konvensi penamaan Pythonic.Ada beberapa tempat yang dapat diterima secara umum
test_module.py
:module.py
.../tests/test_module.py
(pada level yang sama dengan direktori kode).tests/test_module.py
(satu tingkat di bawah direktori kode).Saya lebih suka # 1 karena kesederhanaannya dalam menemukan tes dan mengimpornya. Apa pun sistem pembangunan yang Anda gunakan dapat dengan mudah dikonfigurasi untuk menjalankan file yang dimulai dengan
test_
. Sebenarnya, pola defaultunittest
yang digunakan untuk penemuan tes adalahtest*.py
.sumber
Hanya 1 file uji
Jika hanya memiliki 1 file uji, disarankan untuk menempatkannya di direktori tingkat atas:
Jalankan tes di CLI
Banyak file uji
Jika memiliki banyak file uji, letakkan di
tests
folder:Jalankan tes di CLI
Menggunakan
unittest discovery
unittest discovery
akan menemukan semua tes di folder paket.Buat folder
__init__.py
dalamtests/
Jalankan tes di CLI
Referensi
pytest
Praktik yang Baik untuk tata letak tesunittest
Kerangka uji unit
sumber
Praktik yang umum adalah meletakkan direktori tes di direktori induk yang sama dengan modul / paket Anda. Jadi jika modul Anda disebut foo.py tata letak direktori Anda akan terlihat seperti:
Tentu saja tidak ada cara untuk melakukannya. Anda juga bisa membuat subdirektori tes dan mengimpor modul menggunakan impor absolut .
Di mana pun Anda melakukan tes, saya sarankan Anda menggunakan hidung untuk menjalankannya. Hidung mencari melalui direktori Anda untuk tes. Dengan cara ini, Anda dapat melakukan tes di mana pun mereka membuat paling masuk akal secara organisasi.
sumber
Kami memiliki pertanyaan yang sama ketika menulis Pythoscope ( https://pypi.org/project/pythoscope/ ), yang menghasilkan unit test untuk program Python. Kami mensurvei orang-orang pada pengujian dalam daftar python sebelum kami memilih direktori, ada banyak pendapat berbeda. Pada akhirnya kami memilih untuk meletakkan direktori "tes" di direktori yang sama dengan kode sumber. Dalam direktori itu kami membuat file uji untuk setiap modul di direktori induk.
sumber
Saya juga cenderung untuk menempatkan unit test saya di dalam file itu sendiri, seperti yang dicatat oleh Jeremy Cantrell di atas, meskipun saya cenderung untuk tidak meletakkan fungsi tes di bagian utama, tetapi menempatkan semuanya dalam sebuah
blok. Ini akhirnya menambahkan dokumentasi ke file sebagai 'kode contoh' untuk cara menggunakan file python yang Anda uji.
Saya harus menambahkan, saya cenderung menulis modul / kelas yang sangat ketat. Jika modul Anda membutuhkan jumlah tes yang sangat besar, Anda dapat memasukkannya ke tes lain, tetapi meskipun demikian, saya masih akan menambahkan:
Ini memungkinkan siapa pun yang membaca kode sumber Anda tahu di mana harus mencari kode uji.
sumber
Sesekali saya mendapati diri saya memeriksa topik penempatan tes, dan setiap kali mayoritas merekomendasikan struktur folder terpisah di samping kode perpustakaan, tetapi saya menemukan bahwa setiap kali argumennya sama dan tidak terlalu meyakinkan. Saya akhirnya meletakkan modul tes saya di suatu tempat di samping modul inti.
Alasan utama untuk melakukan ini adalah: refactoring .
Ketika saya memindahkan barang-barang di sekitar saya ingin modul uji untuk bergerak dengan kode; mudah untuk kehilangan tes jika mereka berada di pohon yang terpisah. Mari kita jujur, cepat atau lambat Anda berakhir dengan struktur folder yang sama sekali berbeda, seperti Django , termos dan banyak lainnya. Tidak apa-apa jika Anda tidak peduli.
Pertanyaan utama yang harus Anda tanyakan pada diri sendiri adalah ini:
Apa saya menulis:
Jika sebuah:
Folder terpisah dan upaya ekstra untuk mempertahankan strukturnya mungkin lebih cocok. Tidak ada yang akan mengeluh tentang tes Anda yang digunakan untuk produksi .
Tetapi juga mudah untuk mengecualikan tes dari didistribusikan ketika mereka dicampur dengan folder inti; letakkan ini di setup.py :
Jika b:
Anda mungkin berharap - seperti yang kita semua lakukan - bahwa Anda menulis perpustakaan yang dapat digunakan kembali, tetapi sebagian besar waktu hidup mereka terkait dengan kehidupan proyek. Kemampuan untuk mempertahankan proyek Anda dengan mudah harus menjadi prioritas.
Kemudian jika Anda melakukan pekerjaan dengan baik dan modul Anda cocok untuk proyek lain, itu mungkin akan disalin - tidak bercabang atau dibuat menjadi perpustakaan yang terpisah - ke dalam proyek baru ini, dan memindahkan tes yang ada di sampingnya di struktur folder yang sama mudah dibandingkan dengan memancing tes dalam kekacauan yang menjadi folder tes terpisah. (Anda mungkin berpendapat bahwa itu seharusnya tidak berantakan sejak awal tetapi mari kita bersikap realistis di sini).
Jadi pilihannya tetap milik Anda, tetapi saya berpendapat bahwa dengan tes campuran Anda mencapai semua hal yang sama dengan folder yang terpisah, tetapi dengan sedikit upaya untuk menjaga hal-hal tetap rapi.
sumber
Saya menggunakan
tests/
direktori, dan kemudian mengimpor modul aplikasi utama menggunakan impor relatif. Jadi di MyApp / test / foo.py, mungkin ada:untuk mengimpor
MyApp.foo
modul.sumber
Saya tidak percaya ada "praktik terbaik" yang mapan.
Saya meletakkan tes saya di direktori lain di luar kode aplikasi. Saya kemudian menambahkan direktori aplikasi utama ke sys.path (memungkinkan Anda untuk mengimpor modul dari mana saja) dalam skrip pelari uji saya (yang melakukan beberapa hal lain juga) sebelum menjalankan semua tes. Dengan cara ini saya tidak perlu menghapus direktori tes dari kode utama ketika saya merilisnya, menghemat waktu dan usaha saya, jika jumlah yang sangat kecil.
sumber
os.sys.path.append(os.dirname('..'))
Dari pengalaman saya dalam mengembangkan kerangka kerja pengujian di Python, saya akan menyarankan untuk menempatkan tes unit python di direktori yang terpisah. Pertahankan struktur direktori simetris. Ini akan membantu dalam mengemas hanya perpustakaan inti dan tidak mengemas tes unit. Di bawah ini diimplementasikan melalui diagram skematik.
Dengan cara ini saat Anda mengemas pustaka-pustaka ini menggunakan rpm, Anda bisa mengemas modul pustaka utama (hanya). Ini membantu pemeliharaan terutama di lingkungan yang gesit.
sumber
Saya sarankan Anda memeriksa beberapa proyek Python utama di GitHub dan mendapatkan beberapa ide.
Ketika kode Anda bertambah besar dan Anda menambahkan lebih banyak pustaka, lebih baik membuat folder uji di direktori yang sama dengan yang Anda setup.py dan mirror struktur direktori proyek Anda untuk setiap jenis tes (unittest, integrasi, ...)
Misalnya jika Anda memiliki struktur direktori seperti:
Setelah menambahkan folder uji Anda akan memiliki struktur direktori seperti:
Banyak paket Python yang ditulis dengan benar menggunakan struktur yang sama. Contoh yang sangat bagus adalah paket Boto. Periksa https://github.com/boto/boto
sumber
matplotlib
memilikinya di bawahmatplotlib/lib/matplotlib/tests
( github.com/matplotlib/matplotlib/tree/… ),sklearn
memilikinya di bawahscikitelearn/sklearn/tests
( github.com/scikit-learn/scikit-learn/tree/master/sklearn/tests )Bagaimana saya melakukannya ...
Struktur folder:
Setup.py menunjuk ke src / sebagai lokasi yang berisi modul proyek saya, kemudian saya jalankan:
Yang menambahkan proyek saya ke dalam paket situs, menunjuk ke copy pekerjaan saya. Untuk menjalankan tes saya gunakan:
Menggunakan test runner mana pun yang saya konfigurasikan.
sumber
code.py
. Akan lebih masuk akal untuk memanggil direktori "proyek" tingkat atas.Saya lebih suka direktori tes tingkat atas. Ini berarti impor menjadi sedikit lebih sulit. Untuk itu saya punya dua solusi:
test_suite='tests.runalltests.suite'
ke dalamsetup()
, dan dapat menjalankan tes sederhana:python setup.py test
PYTHONPATH=. python tests/runalltests.py
Begini caranya hal-hal itu didukung oleh kode dalam M2Crypto:
Jika Anda lebih suka menjalankan tes dengan tes suara, Anda mungkin perlu melakukan sesuatu yang sedikit berbeda.
sumber
Kita gunakan
Dalam setiap file tes kita masukkan
../src/
disys.path
. Ini bukan solusi terbaik tetapi berhasil. Saya pikir akan lebih baik jika seseorang datang dengan sesuatu seperti pakar di Jawa yang memberi Anda konvensi standar yang hanya berfungsi, tidak peduli proyek apa yang Anda kerjakan.sumber
Jika tesnya sederhana, cukup letakkan di docstring - sebagian besar kerangka kerja pengujian untuk Python akan dapat menggunakannya:
Untuk tes lain yang lebih terlibat, saya akan memasukkannya ke dalam
../tests/test_module.py
atau ke dalamtests/test_module.py
.sumber
Dalam C #, saya biasanya memisahkan tes menjadi rakitan terpisah.
Dalam Python - sejauh ini - saya cenderung menulis doctests, di mana tesnya ada di docstring suatu fungsi, atau meletakkannya di
if __name__ == "__main__"
blok di bagian bawah modul.sumber
Saat menulis paket yang disebut "foo", saya akan memasukkan tes unit ke dalam paket terpisah "foo_test". Modul dan sub paket kemudian akan memiliki nama yang sama dengan modul paket SUT. Misalnya, tes untuk modul foo.xy ditemukan di foo_test.xy File __init__.py dari setiap paket pengujian kemudian berisi suite AllTests yang mencakup semua suite tes dari paket tersebut. setuptools menyediakan cara mudah untuk menentukan paket pengujian utama, sehingga setelah "python setup.py mengembangkan" Anda bisa menggunakan "python setup.py test" atau "python setup.py test -s foo_test.x.SomeTestSuite" ke hanya suite tertentu.
sumber
Saya meletakkan tes saya di direktori yang sama dengan kode yang diuji (CUT); untuk
foo.py
tes akan masukfoo_ut.py
atau serupa. (Saya mengubah proses penemuan tes untuk menemukan ini.)Ini menempatkan tes tepat di samping kode dalam daftar direktori, membuatnya jelas bahwa tes ada di sana, dan membuat membuka tes semudah mungkin ketika mereka berada di file yang terpisah. (Untuk editor baris perintah,
vim foo*
dan ketika menggunakan browser sistem file grafis, cukup klik pada file CUT dan kemudian file tes yang berbatasan langsung.)Seperti yang telah ditunjukkan orang lain , ini juga membuatnya lebih mudah untuk melakukan refactor dan mengekstrak kode untuk digunakan di tempat lain jika memang diperlukan.
Saya benar-benar tidak menyukai gagasan untuk melakukan tes di pohon direktori yang sama sekali berbeda; mengapa mempersulit pengembang untuk membuka tes saat mereka membuka file dengan CUT? Ini tidak seperti sebagian besar pengembang sangat suka menulis atau mengutak-atik tes yang mereka akan mengabaikan hambatan untuk melakukan itu, daripada menggunakan penghalang sebagai alasan. (Justru sebaliknya, dalam pengalaman saya; bahkan ketika Anda membuatnya semudah mungkin, saya tahu banyak pengembang yang tidak dapat diganggu untuk menulis tes.)
sumber
Saya baru-baru ini mulai memprogram dengan Python, jadi saya belum benar-benar memiliki kesempatan untuk mengetahui praktik terbaik. Tapi, saya sudah menulis modul yang masuk dan menemukan semua tes dan menjalankannya.
Jadi saya punya:
Saya harus melihat bagaimana kelanjutannya ketika saya maju ke proyek yang lebih besar.
sumber