Apa gunanya menjalankan tes unit pada server CI?

98

Mengapa Anda menjalankan tes unit pada server CI?

Tentunya, pada saat sesuatu dikomitmenkan untuk dikuasai, pengembang telah menjalankan semua pengujian unit sebelumnya dan memperbaiki kesalahan yang mungkin terjadi dengan kode baru mereka. Bukankah itu poin dari unit test? Kalau tidak, mereka baru saja melakukan kode yang rusak.

Steve
sumber
51
Pengembang kami tidak diizinkan untuk berkomitmen untuk menguasai. Mereka mendorong ke cabang fitur, server CI kemudian bergabung dengan master dan menjalankan tes. Jika mereka berhasil, maka perubahan digabung untuk dikuasai. Jadi kode dengan tes yang rusak tidak bisa di master ...
Boris the Spider
2
@ BoristheSpider - alur kerja yang sangat bagus. masterharus selalu waras, dan sebaiknya secara otomatis digunakan pada setiap penggabungan ke lingkungan pementasan untuk QA & pengujian internal.
Per Lundberg
130
"Tentunya, pada saat sesuatu dikomitmenkan untuk dikuasai, pengembang telah menjalankan semua tes unit sebelumnya dan memperbaiki kesalahan yang mungkin terjadi dengan kode baru mereka." Kamu tinggal di dunia fantasi apa?
jpmc26
5
Dalam beberapa industri, bagian penting bukan hanya menjalankan tes pada kode, tetapi juga menjalankan tes pada biner . Menjalankan tes pada output CI berarti bahwa Anda dapat menjamin bahwa produk yang dikirimkan berfungsi, karena biner yang diterima klien Anda adalah yang melewati semua tes Anda. Kedengarannya sepele, tetapi kadang-kadang ini dapat memiliki efek (yang saya lihat adalah kebingungan; pada proyek yang kompleks, atau ketika diatur secara aneh, itu dapat menyebabkan masalah pada bangunan yang dikaburkan yang tidak ada dalam versi bersih).
anaximander
5
"Tentunya, pada saat sesuatu dikomitmenkan untuk dikuasai, pengembang telah menjalankan semua tes unit sebelumnya dan memperbaiki kesalahan yang mungkin terjadi dengan kode baru mereka." ... tidak yakin apakah serius
chucksmash

Jawaban:

223

Tentunya, pada saat sesuatu dikomitmenkan untuk dikuasai, pengembang telah menjalankan semua pengujian unit sebelumnya dan memperbaiki kesalahan yang mungkin terjadi dengan kode baru mereka.

Atau tidak. Ada banyak alasan mengapa ini bisa terjadi:

  • Pengembang tidak memiliki disiplin untuk melakukan itu
  • Mereka sudah lupa
  • Mereka tidak melakukan segalanya dan mendorong set komit yang tidak lengkap (terima kasih Matthieu M.
  • Mereka hanya menjalankan beberapa tes, tetapi tidak seluruh rangkaian (terima kasih nhgrif )
  • Mereka menguji pada cabang mereka sebelum penggabungan (terima kasih nhgrif * 2)

Tetapi poin sebenarnya adalah menjalankan tes pada mesin yang bukan mesin pengembang. Satu yang dikonfigurasi secara berbeda.

Ini membantu mengatasi masalah di mana tes dan / atau kode bergantung pada sesuatu yang spesifik untuk kotak pengembang (konfigurasi, data, zona waktu, lokal, apa pun).

Alasan bagus lainnya untuk CI build untuk menjalankan tes:

  • Menguji pada berbagai platform selain dari platform pengembangan utama, yang mungkin sulit dilakukan pengembang. (terima kasih TZHX )
  • Penerimaan / Integrasi / End to End / Tes berjalan sangat lama dapat dijalankan pada server CI yang biasanya tidak akan dijalankan pada kotak pengembang. (terima kasih Ixrec )
  • Pengembang mungkin membuat perubahan kecil sebelum mendorong / melakukan (berpikir ini adalah perubahan yang aman dan karenanya tidak menjalankan tes). (terima kasih Ixrec * 2)
  • Konfigurasi server CI biasanya tidak mencakup semua alat dan konfigurasi pengembang dan karenanya lebih dekat ke sistem produksi
  • Sistem CI membangun proyek dari awal setiap kali, artinya pembangunan berulang
  • Perubahan pustaka dapat menyebabkan masalah hilir - server CI dapat dikonfigurasi untuk membangun semua basis kode dependen, bukan hanya pustaka
Oded
sumber
36
Alasan umum lainnya: 1) Server CI dapat menjalankan tes integrasi / penerimaan tingkat tinggi yang terlalu lama bagi pengembang untuk selalu menjalankannya. 2) Pengembang memang menjalankannya dan kemudian membuat satu perubahan kecil sebelum mendorong bahwa mereka sangat yakin tidak akan merusak apa pun, tetapi kami ingin memastikan.
Ixrec
11
Perubahan ke ketergantungan sering kali juga menjalankan semua build hilir. Jika perubahan yang dilakukan pengembang merusak sesuatu di hilir, itu tidak mudah terlihat ketika memodifikasi perpustakaan (katakanlah mengubah tipe data yang mendasarinya dari SortedSet ke HashSet (hanya menyediakan kontrak Set) dan seseorang di hilir mengerjakan asumsi yang keliru bahwa Set diurutkan). Tidak menjalankan tes (downstream) pada server CI akan membiarkan bug itu membusuk untuk sementara waktu.
2
@ Michael Tangkapan yang bagus. Itulah sebenarnya penyebab> 90% dari kegagalan CI kami hari ini, tidak yakin bagaimana saya melupakannya ...
Ixrec
34
Juga, menjalankannya pada lingkungan CI biasanya berarti Anda mengatur proyek Anda dari awal , memastikan bangunan Anda dapat diulang .
mgarciaisaia
5
Juga, dua perubahan dapat dilakukan yang diuji baik-baik saja secara terpisah, tetapi pecah bersama (misalnya satu menghapus API yang tidak digunakan, dan yang lainnya mulai menggunakannya).
Simon Richter
74

Sebagai pengembang yang tidak menjalankan semua tes integrasi dan unit sebelum membuat komit ke kontrol sumber, saya akan menawarkan pertahanan saya di sini.

Saya harus membuat, menguji, dan memverifikasi bahwa aplikasi berjalan dengan benar di:

  • Microsoft Windows XP dan Vista dengan kompiler Visual Studio 2008.
  • Microsoft Windows 7 dengan kompiler Visual Studio 2010.
    • Oh, dan MSI dibuat untuk masing-masing.
  • RHEL 5 dan 6 masing-masing dengan 4,1 dan 4,4 (sama dengan CentOS)
    • 7 segera. Woop-de-woop.
  • Fedora Workstation dengan GCC untuk tiga versi terakhir.
  • Debian (dan turunannya seperti Ubuntu) untuk tiga versi terakhir.
  • Mac OSX dalam tiga versi terakhir.
    • Dan paketnya (rpm, dmg, dll)

Tambahkan Fortran (dengan kompiler Intel dan GNU), Python (dan berbagai versi tergantung pada OS) dan komponen skrip bash / bat dan, well, saya pikir Anda dapat melihat hal-hal berputar keluar

Jadi itu enam belas mesin yang harus saya miliki, hanya untuk menjalankan beberapa tes beberapa kali sehari. Hampir menjadi pekerjaan penuh waktu hanya untuk mengelola infrastruktur untuk itu. Saya pikir hampir semua orang akan setuju bahwa itu tidak masuk akal, terutama mengalikannya dengan jumlah orang dalam proyek. Jadi kami membiarkan server CI kami melakukan pekerjaan.

Tes unit tidak menghentikan Anda melakukan kode rusak, mereka memberi tahu Anda jika mereka tahu Anda telah merusak sesuatu. Orang-orang dapat mengatakan "unit test harus cepat", dan melanjutkan tentang prinsip dan pola desain serta metodologi, tetapi pada kenyataannya kadang-kadang lebih baik membiarkan komputer yang kami rancang untuk tugas berulang dan monoton melakukan hal itu dan hanya terlibat jika mereka beri tahu kami bahwa mereka telah menemukan sesuatu.

TZHX
sumber
3
Kode tes pengujian unit bukan konfigurasi. Anda akan sangat malas untuk menambahkan tes baru dan melemparkannya ke dinding tanpa menjalankannya terlebih dahulu secara lokal ...
Robbie Dee
33
@RobbieDee, saya khawatir saya tidak mengerti maksud Anda? Saya tidak menyarankan membuat tes baru tanpa mengujinya secara lokal, atau hanya secara buta melakukan hal-hal ke kontrol sumber tanpa mengujinya sendiri, dan saya akan menjalankan tes pada mesin saya sendiri - tetapi "konfigurasi" perlu diuji untuk perilaku yang konsisten , dan itu lebih baik untuk melakukan itu relatif cepat ketika pikiran pengembang masih di daerah itu daripada menemukan masalah ketika tim yang sebagian besar menggunakan Mac bangun empat ribu mil jauhnya dan memperbarui salinan mereka.
TZHX
7
@RobbieDee Saya akan mengatakan TZHX akan menjalankan semua tes secara lokal jika mereka bisa melakukannya, tetapi mereka tidak bisa . Karena TZHX tidak bisa, mereka menjalankan beberapa tes secara lokal (yang dapat berjalan pada sistem dev mereka dan cukup pendek atau paling relevan dengan kode yang diubah, misalnya), dan membiarkan baterai penuh berjalan pada sistem CI. Cukup masuk akal.
muru
11
@RobbieDee: Dia percaya pada pengujian unit. Jadi dia menguji mereka di Macbook air-nya dan lulus dan check in. Server CI yang menjalankan Red Hat, Solaris dan Windows kemudian menjalankan tes-tes itu lagi. Bukankah senang mengetahui bahwa apa yang Anda uji juga bekerja pada platform produksi?
Slebetman
2
@RobbieDee: Saya sering menulis Tes Unit yang khusus untuk kompiler tertentu pada platform tertentu. Pertimbangkan misalnya subsistem grafik yang menggunakan instruksi CPU spesifik AMD (pesaing Intel) yang hanya tersedia pada g ++ (kompiler GNU C ++) versi 4.5 atau lebih baru, tetapi saya kebetulan bekerja pada CPU Atom dan ICC (Intel C ++ Penyusun). Tidak masuk akal untuk menjalankan tes AMD / g ++ 4.5 setiap kali pada mesin itu, namun ini adalah kode yang harus diuji sebelum dirilis; ditambah kode CPU-independent saya sendiri harus diuji untuk interoperabilitas yang tepat. Tentu, ada VM dan emulator, ...
phresnel
23

Terlepas dari jawaban Oded yang sangat baik:

  • Anda menguji kode dari repositori . Ini dapat bekerja pada mesin Anda dengan file Anda ... yang Anda lupa komit. Ini mungkin bergantung pada tabel baru yang tidak memiliki skrip pembuatan (Dalam liquibase misalnya), beberapa data konfigurasi atau file properti.
  • Anda menghindari masalah integrasi kode. Satu pengembang mengunduh versi terakhir, membuat uji unit dan integrasi, menambahkan kode, lulus semua tes di mesinnya, melakukan dan mendorong. Pengembang lain baru saja melakukan hal yang sama. Kedua perubahan itu benar sendiri tetapi bila digabungkan menyebabkan bug. Ini bisa menjadi penggabungan repositori atau hanya saja itu tidak terdeteksi sebagai konflik. Misalnya Dev 1 menghapus file yang tidak digunakan sama sekali. Dev 2 kode terhadap file ini dan tes tanpa perubahan Dev 1.
  • Anda mengembangkan skrip untuk digunakan secara otomatis dari repositori. Memiliki skrip pembangunan dan penempatan universal memecahkan banyak masalah. Beberapa pengembang mungkin telah menambahkan lib atau opsi kompilasi yang tidak dibagikan oleh semua orang. Ini tidak hanya menghemat waktu Anda, tetapi yang lebih penting, ini membuat penyebaran aman dan dapat diprediksi. Selanjutnya, Anda bisa kembali ke repositori ke versi 2.3.1 dan menggunakan versi ini dengan skrip yang berfungsi dengan versi ini. Ini termasuk objek basis data seperti tampilan, prosedur tersimpan, tampilan, dan pemicu yang harus diversi. (Atau Anda tidak akan dapat kembali ke versi yang bisa diterapkan).
  • Tes lain : Seperti integrasi, kinerja, dan tes ujung ke ujung. Ini bisa lambat dan mungkin termasuk alat pengujian seperti Selenium. Anda mungkin memerlukan set data lengkap dengan database nyata, bukan objek tiruan atau HSQL.

Saya pernah bekerja di perusahaan yang memiliki banyak bug pada penyebaran karena proses penggabungan dan penyebaran. Ini disebabkan oleh kerangka kerja aneh yang membuat pengujian dan CI sulit. Itu bukan pengalaman yang menyenangkan untuk menemukan bahwa kode yang bekerja dengan baik pada pengembangan tidak tiba tepat untuk produksi.

Borjab
sumber
Ya, hanya lupa untuk melakukan beberapa perubahan sangat umum. Saya akan mengatakan lupa untuk "svn add" file baru dan jadi lupa untuk mengkomitnya nanti adalah cara paling populer untuk mendapatkan pembuatan otomatis yang gagal.
sharptooth
22

Anda akan berpikir begitu kan - tetapi pengembang adalah manusia dan mereka terkadang lupa.

Juga, pengembang sering gagal menarik kode terbaru. Tes terbaru mereka mungkin berjalan baik maka pada saat check-in, orang lain melakukan perubahan besar.

Tes Anda juga dapat mengandalkan sumber daya lokal (tidak dicentang). Sesuatu yang tidak akan diambil unit test lokal Anda.

Jika Anda berpikir semua hal di atas fantastis, ada tingkat di atas CI (setidaknya di TFS) yang disebut Gated di mana bangunan yang memiliki tes gagal disimpan dan tidak berkomitmen pada basis kode.

Robbie Dee
sumber
7
Saya telah melihat lebih banyak oops, saya lupa untuk melakukan kegagalan CI yang ingin saya akui.
Dan Neely
@DanNeely Agar adil, ini mengalahkan pantat Anda ditendang oleh manajer bangunan karena Anda lupa memberi tahu dia tentang sesuatu ... :-)
Robbie Dee
3
Itulah salah satu alasan saya mencintai CI. Menemukan dan memperbaiki ooopses Anda sendiri jauh lebih baik daripada meminta orang lain menemukannya untuk Anda.
Dan Neely
14

pada saat sesuatu berkomitmen untuk dikuasai

Saya biasanya mengatur CI saya untuk dijalankan di setiap komit tunggal. Cabang tidak digabung menjadi master sampai cabang diuji. Jika Anda mengandalkan menjalankan tes pada master, maka itu membuka jendela untuk membangun yang akan rusak.

Menjalankan tes pada mesin CI adalah tentang hasil yang dapat direproduksi. Karena server CI memiliki lingkungan bersih yang diketahui berasal dari VCS Anda, Anda tahu bahwa hasil pengujiannya benar. Saat berjalan secara lokal, Anda bisa lupa untuk mengkomit beberapa kode yang diperlukan agar mereka lulus, atau memiliki kode yang tidak dikomit yang membuat mereka lulus ketika mereka seharusnya gagal.

Ini juga dapat menghemat waktu pengembang dengan menjalankan berbagai suite secara paralel, terutama jika beberapa tes lambat, multi-menit yang tidak mungkin dijalankan secara lokal setelah setiap perubahan.

Pada pekerjaan saya saat ini, penyebaran produksi kami terjaga keamanannya pada CI melewati semua tes. Script deploy akan mencegah penyebaran kecuali mereka lewat. Ini membuat mustahil untuk secara tidak sengaja lupa menjalankannya.

CI yang menjadi bagian dari alur kerja juga membebani pengembang. Sebagai pengembang, apakah Anda biasanya menjalankan linter, analisa statis, uji unit, cakupan kode, dan uji integrasi untuk setiap perubahan tunggal? CI dapat, sepenuhnya otomatis dan tanpa perlu memikirkannya - mengurangi keletihan keputusan.

Daenyth
sumber
1
Anda seharusnya tidak benar-benar memiliki tes unit lambat - ini melanggar prinsip PERTAMA .
Robbie Dee
4
@RobbieDee: Saya pikir biasanya server CI menjalankan semua tes, bukan hanya tes unit.
RemcoGerlich
4
@RobbieDee: dalam teori semua tes unit cepat. Dalam praktek .... Apapun, CI dapat dan harus menjalankan semua tes - linter, analisis statis, tes unit, tes integrasi.
Daenyth
2
@RobbieDee Jelas spesifikasi konfigurasi akan bervariasi dari satu tim ke tim lainnya. Bahkan ketika build memakan waktu beberapa menit, seringkali dimungkinkan untuk menjalankan beberapa build secara paralel. Dengan basis kode monolitik tunggal, ini bisa menjadi kelemahan yang lebih besar, tetapi IME itu bukan penghalang.
Daenyth
1
@RobbieDee Saya pikir ini lebih tergantung pada arsitektur Anda. Saya telah melihatnya bekerja dengan tangan untuk tim teknik ~ 80, tapi itu dengan sub-tim yang jelas untuk area produk.
Daenyth
4

Pada saat sesuatu berkomitmen untuk dikuasai, pengembang seharusnya sudah menjalankan semua tes unit ... tetapi bagaimana jika belum? Jika Anda tidak menjalankan tes unit pada server CI, Anda tidak akan tahu sampai orang lain menarik perubahan ke mesin mereka dan menemukan tes yang baru saja rusak.

Selain itu, pengembang mungkin telah melakukan kesalahan dan mereferensikan sumber daya lokal khusus untuk mesin mereka. Ketika mereka memeriksa kode dan menjalankan CI gagal, masalah segera diidentifikasi dan dapat diperbaiki.

David Arno
sumber
3

Dengan asumsi (bertentangan dengan jawaban lain) bahwa pengembang cukup disiplin dan melakukan tes unit sebelum melakukan, mungkin ada beberapa alasan:

  • menjalankan unit test bisa memakan waktu lama untuk beberapa pengaturan khusus. Misalnya, menjalankan tes unit dengan pemeriksa memori (seperti valgrind) dapat memakan waktu lebih lama. Meskipun semua tes unit lulus, pemeriksaan memori bisa gagal.
  • hasilnya tidak begitu penting untuk beberapa pengaturan khusus - misalnya, menjalankan tes unit untuk memeriksa cakupan kode memerlukan flag kompilasi khusus. Untuk pengembang normal, cakupan kode tidak begitu penting - lebih penting bagi orang yang menjaga kode menjaga kualitas tertentu, seperti lead tim.
BЈовић
sumber
3

Dimungkinkan untuk membayangkan kasus ketika perubahan A tidak merusak tes, dan perubahan B tidak merusak tes, tetapi A dan B bersama - sama melakukannya. Jika A dan B dibuat oleh pengembang yang berbeda, hanya server CI yang akan mendeteksi bug baru. A dan B bahkan mungkin dua bagian dari kalimat yang lebih panjang yang sama.

Bayangkan sebuah kereta yang dikendarai oleh dua lokomotif A dan B. Mungkin satu lebih dari cukup dan ini adalah perbaikan untuk diterapkan. Namun jika kedua "perbaikan" diterapkan menghapus keduanya, kereta tidak akan bergerak.

Juga, tidak semua pengembang menjalankan semua tes Unit, sementara sebagian besar pengembang yang baik melakukannya.

h22
sumber
2

Mari kita ajukan pertanyaan yang setara:

Mengapa Anda membuat kode pada server CI?

Tentunya, pada saat sesuatu dikomitmenkan untuk dikuasai, pengembang telah membangun kode sebelumnya dan memperbaiki kesalahan yang mungkin terjadi dengan kode baru mereka. Bukankah itu inti dari kode bangunan? Kalau tidak, mereka baru saja melakukan kode yang rusak.


Ada beberapa alasan untuk melakukan CI, tetapi poin utama CI adalah untuk mendapatkan gambaran tentang status kode dari waktu ke waktu. Manfaat utama (dari beberapa) ini memberikan, adalah bahwa kita dapat mengetahui kapan build rusak, mencari tahu apa yang memecahkannya, dan kemudian memperbaikinya.

Jika kodenya tidak pernah rusak, mengapa kita menggunakan CI? Untuk mengirimkan build untuk pengujian, build malam akan cukup baik.

Peter
sumber