Kami telah mencapai titik dalam proyek kami di mana kami memiliki hampir seribu tes dan orang-orang telah berhenti repot-repot menjalankannya sebelum melakukan check-in karena butuh waktu lama. Paling-paling mereka menjalankan tes yang relevan dengan potongan kode yang mereka ubah dan paling buruk mereka hanya memeriksanya tanpa pengujian.
Saya percaya masalah ini disebabkan oleh kenyataan bahwa solusinya telah berkembang menjadi 120 proyek (kami biasanya melakukan proyek yang jauh lebih kecil dan ini hanya kedua kalinya kami melakukan TDD dengan benar) dan waktu uji build + telah berkembang menjadi sekitar dua-tiga menit pada mesin yang lebih rendah.
Bagaimana kita menurunkan waktu uji? Apakah ada teknik? Berpura-pura lebih banyak? Kurang berpura-pura? Mungkin tes integrasi yang lebih besar tidak boleh berjalan secara otomatis saat menjalankan semua tes?
Sunting: sebagai tanggapan terhadap beberapa jawaban, kami sudah menggunakan CI dan server build, ini adalah bagaimana saya tahu tes gagal. Masalahnya (sebenarnya sebuah gejala) adalah kami terus menerima pesan tentang bangunan yang gagal. Menjalankan tes parsial adalah sesuatu yang dilakukan kebanyakan orang tetapi tidak semua. dan mengenai tes, mereka sebenarnya dibuat dengan cukup baik, mereka menggunakan palsu untuk semuanya dan tidak ada IO sama sekali.
sumber
Jawaban:
Solusi yang mungkin adalah memindahkan bagian pengujian dari mesin pengembangan ke pengaturan integrasi berkelanjutan ( Jenkins misalnya) menggunakan perangkat lunak kontrol versi dari beberapa rasa ( git , svn , dll ...).
Ketika kode baru harus ditulis, pengembang yang diberikan akan membuat cabang untuk apa pun yang mereka lakukan di repositori. Semua pekerjaan akan dilakukan di cabang ini dan mereka dapat melakukan perubahan mereka ke cabang kapan saja tanpa mengacaukan baris kode utama.
Ketika fitur yang diberikan, perbaikan bug, atau apa pun yang sedang mereka kerjakan telah selesai, cabang tersebut dapat digabungkan kembali ke bagasi (atau bagaimanapun Anda lebih suka melakukannya) di mana semua unit test dijalankan. Jika tes gagal, gabungan ditolak dan pengembang diberitahu sehingga mereka dapat memperbaiki kesalahan.
Anda juga dapat meminta server CI Anda menjalankan unit test pada setiap cabang fitur saat komit dibuat. Dengan cara ini pengembang dapat membuat beberapa perubahan, mengkomit kode, dan membiarkan server menjalankan tes di latar belakang sementara mereka terus bekerja pada perubahan tambahan atau proyek lainnya.
Panduan hebat untuk satu cara melakukan pengaturan seperti itu dapat ditemukan di sini (spesifik git tetapi harus bekerja untuk sistem kontrol versi lainnya): http://nvie.com/posts/a-successful-git-branching-model/
sumber
Mayoritas Tes Unit harus masing-masing kurang dari 10 milidetik. Memiliki 'hampir seribu tes' bukanlah apa - apa dan harus berjalan mungkin beberapa detik.
Jika tidak, maka Anda harus berhenti menulis tes integrasi yang sangat berpasangan (kecuali jika itu yang dibutuhkan kode) dan mulai menulis tes unit yang baik (dimulai dengan kode yang dipisahkan dengan baik dan penggunaan yang benar dari palsu / mock / stubs / dll). Penggandaan itu akan memengaruhi kualitas tes dan waktu yang diperlukan untuk menulisnya juga - jadi itu bukan hanya masalah mengurangi waktu uji coba.
sumber
py.test
) melakukan banyak keajaiban di latar belakang, dan semuanya menjadi kode Python murni ("100x lebih lambat dari C "), menjalankan sekitar 500 tes dalam proyek saya membutuhkan waktu kurang dari 6 detik pada netbook yang lambat beberapa tahun. Angka ini kira-kira linier dalam jumlah tes; sementara ada beberapa overhead start-up, itu diamortisasi atas semua tes, dan overhead per-tes adalah O (1).Ada beberapa pendekatan yang saya gunakan untuk menyelesaikan masalah serupa:
Selain itu, Anda dapat menggunakan alat berikut untuk membuat hidup Anda mudah dan tes berjalan lebih cepat
pnunit
dan konfigurasi CI dengan beberapa node.sumber
0. Dengarkan pemrogram Anda.
Jika mereka tidak menjalankan tes, itu berarti mereka menganggap biaya (menunggu tes untuk menjalankan, berurusan dengan kegagalan palsu) menjadi lebih besar daripada nilai (menangkap bug segera). Kurangi biaya, tambah nilainya, dan orang akan menjalankan tes setiap saat.
1. Jadikan tes Anda 100% andal.
Jika Anda pernah memiliki tes yang gagal dengan negatif palsu, segera atasi itu. Perbaiki, ubah, hapus, apa pun yang diperlukan untuk menjamin keandalan 100%. (Tidak masalah memiliki serangkaian tes yang tidak dapat diandalkan, tetapi masih berguna yang dapat Anda jalankan secara terpisah, tetapi bagian utama dari tes harus dapat diandalkan.)
2. Ubah sistem Anda untuk menjamin bahwa semua tes lulus sepanjang waktu.
Gunakan sistem integrasi berkesinambungan untuk memastikan bahwa hanya komit yang lewat yang digabungkan ke cabang utama / resmi / rilis / apa pun.
3. Ubah budaya Anda untuk menghargai tes kelulusan 100%.
Ajarkan pelajaran bahwa tugas tidak "selesai" sampai 100% tes lulus dan telah digabungkan ke cabang utama / resmi / rilis / apa pun.
4. Buat tes cepat.
Saya telah mengerjakan proyek di mana tes mengambil kedua, dan pada proyek di mana mereka mengambil sepanjang hari. Ada korelasi kuat antara waktu yang diperlukan untuk menjalankan tes dan produktivitas saya.
Semakin lama tes dijalankan, semakin jarang Anda menjalankannya. Itu berarti Anda akan pergi lebih lama tanpa mendapat umpan balik tentang perubahan yang Anda buat. Ini juga berarti Anda akan lebih lama di antara komitmen. Berkomitmen lebih sering berarti langkah-langkah kecil yang lebih mudah untuk digabungkan; komit sejarah lebih mudah diikuti; menemukan bug dalam sejarah lebih mudah; memutar kembali lebih mudah juga.
Bayangkan tes yang berjalan sangat cepat sehingga Anda tidak keberatan menjalankannya setiap kali dikompilasi.
Membuat tes cepat bisa sulit (itu yang diminta OP, kan!). Decoupling adalah kuncinya. Mengolok-olok / palsu tidak apa-apa, tapi saya pikir Anda bisa melakukan lebih baik dengan refactoring untuk membuat mengolok-olok / palsu tidak perlu. Lihat blog Arlo Belshee, dimulai dengan http://arlobelshee.com/post/the-no-mocks-book .
5. Jadikan tes bermanfaat.
Jika tes tidak gagal ketika Anda gagal, lalu apa gunanya? Ajari diri Anda untuk menulis tes yang akan menangkap bug yang mungkin Anda buat. Ini adalah keterampilan tersendiri, dan akan membutuhkan banyak perhatian.
sumber
Beberapa menit tidak masalah untuk unit test. Namun, perlu diingat bahwa ada 3 jenis tes utama:
Ini tercantum dalam urutan kecepatan. Tes unit harus cepat. Mereka tidak akan menangkap setiap bug, tetapi mereka menetapkan bahwa program ini cukup waras. Tes unit harus berjalan dalam 3 menit atau kurang atau perangkat keras yang layak. Anda mengatakan Anda hanya memiliki 1000 unit tes, dan itu memakan waktu 2-3 menit? Yah, itu mungkin baik-baik saja.
Hal-hal yang perlu diperiksa:
Pastikan untuk memastikan bahwa pengujian unit dan uji integrasi Anda terpisah. Tes integrasi akan selalu lebih lambat.
Pastikan unit test Anda berjalan secara paralel. Tidak ada alasan bagi mereka untuk tidak melakukannya jika itu adalah unit test yang benar
Pastikan pengujian unit Anda "bebas ketergantungan". Mereka seharusnya tidak pernah mengakses database atau sistem file
Selain itu, tes Anda tidak terdengar terlalu buruk saat ini. Namun, untuk referensi, salah satu teman saya di tim Microsoft memiliki 4.000 unit tes yang berjalan di bawah 2 menit pada perangkat keras yang layak (dan ini adalah proyek yang rumit). Mungkin untuk memiliki tes unit cepat. Menghilangkan ketergantungan (dan mengejek hanya sebanyak yang dibutuhkan) adalah hal utama untuk mendapatkan kecepatan.
sumber
Latih pengembang Anda tentang Proses Perangkat Lunak Pribadi (PSP) membantu mereka memahami dan meningkatkan kinerja mereka dengan menggunakan lebih banyak disiplin. Menulis kode tidak ada hubungannya dengan membanting jari Anda pada keyboard dan kemudian tekan tombol kompilasi dan check in.
PSP dulu sangat populer di masa lalu ketika mengkompilasi kode adalah proses yang membutuhkan banyak waktu (jam / hari pada mainframe sehingga semua orang harus berbagi kompilator). Tetapi ketika workstation pribadi menjadi lebih kuat, kita semua datang untuk menerima proses:
Jika Anda berpikir sebelum mengetik, dan setelah mengetik, tinjau apa yang Anda tulis, Anda bisa mengurangi jumlah kesalahan sebelum menjalankan build and test suite. Belajarlah untuk tidak menekan build 50 kali sehari, tetapi mungkin sekali atau dua kali, maka itu kurang penting bahwa build dan waktu pengujian Anda membutuhkan beberapa menit lebih lama.
sumber
Salah satu cara yang mungkin: pisahkan solusi Anda. Jika suatu solusi memiliki 100 proyek, maka itu tidak dapat dikelola. Hanya karena dua proyek (katakanlah A dan B) menggunakan beberapa kode umum dari proyek lain (katakanlah Lib) tidak berarti mereka harus berada dalam solusi yang sama.
Sebagai gantinya, Anda dapat membuat solusi A dengan proyek A dan Lib dan juga solusi B dengan proyek B dan Lib.
sumber
Saya dalam situasi yang sama. Saya memiliki unit test yang menguji komunikasi dengan server. Mereka menguji perilaku dengan timeout, membatalkan koneksi, dll. Seluruh rangkaian tes berlangsung 7 menit.
7 menit adalah waktu yang relatif singkat tetapi itu bukan sesuatu yang akan Anda lakukan sebelum setiap komit.
Kami juga memiliki serangkaian uji UI otomatis, waktu tayangnya adalah 2 jam. Ini bukan sesuatu yang ingin Anda jalankan setiap hari di komputer Anda.
Jadi, apa yang harus dilakukan?
Yang penting adalah: semua tes Anda harus sering dijalankan karena penting untuk menemukan bug. Namun, itu tidak mutlak diperlukan untuk menemukan mereka sebelum melakukan.
sumber
Meskipun uraian masalah Anda tidak memberikan wawasan menyeluruh tentang basis kode, saya pikir saya bisa mengatakan bahwa masalah Anda aman dua kali lipat.
Belajar menulis tes yang tepat.
Anda mengatakan Anda memiliki hampir seribu tes, dan Anda memiliki 120 proyek. Dengan asumsi bahwa sebagian besar dari proyek-proyek tersebut adalah proyek uji, Anda memiliki 1000 pengujian hingga 60 proyek kode produksi. Itu memberi Anda sekitar 16-17 tes pr. proyek!!!
Itu mungkin jumlah tes yang harus saya ikuti sekitar 1-2 kelas dalam sistem produksi. Jadi, kecuali Anda hanya memiliki 1-2 kelas di setiap proyek (dalam hal ini struktur proyek Anda terlalu halus) tes Anda terlalu besar, mereka mencakup terlalu banyak tanah. Anda mengatakan ini adalah proyek pertama yang Anda lakukan TDD dengan benar. Katakanlah, angka yang Anda tunjukkan menunjukkan bahwa ini bukan masalahnya, Anda tidak melakukan properti TDD.
Anda harus belajar menulis tes yang tepat, yang mungkin berarti Anda harus belajar bagaimana membuat kode dapat diuji di tempat pertama. Jika Anda tidak dapat menemukan pengalaman di dalam tim untuk melakukan itu, saya sarankan untuk menyewa bantuan dari luar, misalnya dalam bentuk satu atau dua konsultan yang membantu tim Anda selama 2-3 bulan untuk belajar menulis kode yang dapat diuji, dan sedikit tes unit minimal.
Sebagai perbandingan, pada proyek .NET yang sedang saya kerjakan, kita dapat menjalankan sekitar 500 unit tes dalam waktu kurang dari 10 detik (dan itu bahkan tidak diukur pada mesin spec tinggi). Jika itu adalah angka-angka Anda, Anda tidak akan takut untuk menjalankan ini secara lokal sesering mungkin.
Belajarlah untuk mengelola struktur proyek.
Anda telah membagi solusi menjadi 120 proyek. Itu menurut standar saya jumlah proyek yang mengejutkan.
Jadi jika masuk akal untuk benar-benar memiliki jumlah proyek (yang saya rasa tidak - tetapi pertanyaan Anda tidak memberikan informasi yang cukup untuk membuat penilaian yang berkualitas dari ini), Anda perlu membagi proyek menjadi komponen yang lebih kecil yang dapat dibangun, versi, dan digunakan secara terpisah. Jadi ketika pengembang menjalankan unit test suite, ia hanya perlu menjalankan tes yang berkaitan dengan komponen yang sedang dikerjakannya saat ini. Server build harus memastikan bahwa semuanya terintegrasi dengan benar.
Tetapi memisahkan proyek dalam beberapa komponen, membangun, versi, dan digunakan secara terpisah membutuhkan pengalaman saya tim pengembangan yang sangat matang, tim yang lebih matang daripada saya merasa bahwa tim Anda adalah.
Tetapi bagaimanapun juga, Anda perlu melakukan sesuatu tentang struktur proyek. Baik membagi proyek menjadi komponen yang terpisah, atau mulai menggabungkan proyek.
Tanyakan pada diri Anda apakah Anda benar-benar membutuhkan 120 proyek?
ps Anda mungkin ingin memeriksa NCrunch. Ini adalah Visual Studio plug-in yang menjalankan pengujian Anda secara otomatis di latar belakang.
sumber
Tes JUnit biasanya harus cepat, tetapi beberapa dari mereka harus meluangkan waktu untuk mengeksekusi.
Sebagai contoh, tes database biasanya memerlukan beberapa waktu untuk menginisialisasi dan menyelesaikan.
Jika Anda memiliki ratusan tes, meskipun cepat, tes tersebut memerlukan banyak waktu untuk dijalankan karena jumlahnya.
Apa yang bisa dilakukan adalah:
1) Identifikasi tes penting. Mereka untuk bagian paling penting dari perpustakaan dan yang paling mungkin gagal setelah perubahan. Hanya tes-tes yang harus dijalankan selalu pada kompilasi. Jika beberapa kode sering rusak, pengujiannya harus diwajibkan bahkan jika mereka membutuhkan waktu lama untuk dieksekusi, di sisi lain, jika beberapa bagian dari perangkat lunak tidak pernah menyebabkan masalah, Anda dapat melewati pengujian dengan aman pada setiap pembuatan.
2) Siapkan server integrasi berkelanjutan, yang akan menjalankan semua tes di latar belakang. Terserah Anda jika Anda memutuskan untuk membangun setiap jam atau membangun setelah setiap komit (yang kedua masuk akal hanya jika Anda ingin secara otomatis mendeteksi komit yang menyebabkan masalah).
sumber
Masalah yang saya lihat:
a) Menggunakan IOC untuk membangun elemen uji. 70 detik -> 7 detik dengan menghapus Kontainer.
b) Tidak mengejek semua kelas. Simpan unit test Anda ke satu elemen. Saya telah melihat tes yang mengoceh melalui beberapa kelas. Ini bukan tes unit dan lebih mungkin untuk pecah.
c) Profil mereka untuk mengetahui apa yang terjadi. Saya menemukan konstruktor sedang membangun barang-barang yang tidak saya butuhkan jadi saya melokalkannya dan mengurangi waktu berjalan.
d) Profil. mungkin kodenya tidak begitu bagus dan Anda bisa mendapatkan efisiensi dari ulasan.
e) Hapus ketergantungan. Menjaga agar tes Anda kecil dapat dieksekusi akan mengurangi waktu memuat. Gunakan pustaka antarmuka dan wadah IOC untuk menjalankan solusi akhir Anda, tetapi proyek pengujian utama Anda hanya harus memiliki pustaka antarmuka yang ditentukan. Ini memastikan pemisahan, memastikan lebih mudah untuk menguji, dan juga membuat kaki tes Anda lebih kecil.
sumber
Saya merasakan sakit Anda, dan saya telah berlari ke beberapa tempat di mana kecepatan build dapat ditingkatkan banyak. Namun, angka pada hal yang saya sarankan adalah mengukur pada detail granular untuk mencari tahu di mana bangunan Anda mengambil paling lama. Misalnya, saya memiliki bangunan dengan sekitar 30 proyek yang membutuhkan waktu lebih dari satu menit untuk berjalan. Namun, itu hanya sebagian dari gambar. Saya juga tahu proyek mana yang paling lama dibangun, yang membantu memfokuskan upaya saya.
Hal-hal yang memakan waktu membangun:
Perpustakaan tiruan baik menggunakan refleksi atau menyuntikkan kode menggunakan perpustakaan bytecode untuk menghasilkan tiruan untuk Anda. Meskipun sangat nyaman, ia memakan waktu tes. Jika Anda membuat tiruan di dalam loop dalam pengujian Anda, ini dapat menambah jumlah waktu yang terukur untuk pengujian unit.
Ada beberapa cara untuk memperbaiki masalah:
Ketika solusi Anda berisi lebih dari 100 proyek, Anda memiliki kombinasi kode perpustakaan, tes, dan kode aplikasi. Setiap perpustakaan dapat menjadi solusi sendiri dengan tes terkait itu. Jet Brains Team City adalah server pembangun CI yang juga berfungsi sebagai server Nuget - dan saya yakin itu bukan satu-satunya. Itu memberi Anda fleksibilitas untuk memindahkan perpustakaan yang mungkin tidak sering berubah ke solusi / proyek mereka sendiri dan menggunakan Nuget untuk menyelesaikan dependensi untuk kode aplikasi Anda. Solusi yang lebih kecil berarti Anda dapat membuat perubahan ke perpustakaan dengan cepat dan tanpa keributan, dan nikmati manfaatnya dalam solusi utama.
sumber
Dapatkah lingkungan pengujian Anda berjalan di mana saja? Jika bisa, gunakan komputasi awan untuk menjalankan tes. Bagi tes di antara mesin virtual N. Jika waktu untuk menjalankan tes pada satu mesin adalah T1 detik, maka waktu untuk menjalankannya berpisah, T2, dapat mendekati T2 = T1 / N. (Dengan asumsi setiap test case membutuhkan jumlah waktu yang sama.) Dan Anda hanya perlu membayar untuk VMs ketika Anda menggunakannya. Jadi Anda tidak memiliki banyak mesin uji yang sedang duduk di lab di suatu tempat 24/7. (Saya ingin sekali dapat melakukan ini di tempat saya bekerja, tetapi kami terikat dengan perangkat keras tertentu. Tidak ada VM untuk saya.)
sumber