Apakah unit test akan membantu Citigroup untuk menghindari kesalahan mahal ini?

86

Saya membaca tentang snafu ini: Biaya pemrograman bug Citigroup $ 7 juta setelah transaksi yang sah keliru untuk data pengujian selama 15 tahun .

Ketika sistem diperkenalkan pada pertengahan 1990-an, kode program menyaring semua transaksi yang diberi kode cabang tiga digit dari 089 hingga 100 dan menggunakan awalan itu untuk tujuan pengujian.

Tetapi pada tahun 1998, perusahaan mulai menggunakan kode cabang alfanumerik ketika memperluas bisnisnya. Di antara mereka adalah kode 10B, 10C dan seterusnya, yang sistem diperlakukan sebagai dalam kisaran yang dikecualikan, dan transaksi mereka dihapus dari laporan yang dikirim ke SEC.

(Saya pikir ini menggambarkan bahwa menggunakan indikator data non-eksplisit adalah ... sub-optimal. Akan jauh lebih baik untuk mengisi dan menggunakan properti semantik eksplisit Branch.IsLive.)

Selain itu, reaksi pertama saya adalah "Tes unit akan membantu di sini" ... tetapi apakah mereka?

Saya baru-baru ini membaca Mengapa kebanyakan pengujian unit sia - sia , dan pertanyaan saya adalah: seperti apa pengujian unit yang gagal pada pengenalan kode cabang alfanumerik?

Matt Evans
sumber
17
Tampaknya mereka juga melewatkan tes integrasi yang memeriksa jumlah transaksi yang diekspor ke SEC. Jika Anda membangun fitur ekspor itu akan menjadi pemeriksaan yang masuk akal.
Luc Franken
31
Penulis artikel tampaknya tidak mengerti pengujian unit. Beberapa klaim benar-benar konyol ( "unit test tidak mungkin menguji lebih dari sepersepuluh dari fungsionalitas metode tertentu" ), yang lain akan menghancurkan peluang mendapatkan regresi ( "lihat tes yang tidak pernah gagal dalam setahun dan pertimbangkan membuangnya " ). Atau saran seperti " ubah unit test menjadi asersi" , yang seharusnya mengubah tes gagal untuk pengecualian runtime?
Groo
25
@gnat Saya tidak membaca tautan eksternal, dan saya masih menemukan pertanyaan ini bermakna
Jeutnarg
23
Untuk apa nilainya, saya sangat tidak setuju dengan semua yang ada di "Mengapa Sebagian Besar Unit Pengujian adalah Pemborosan." Saya akan menulis bantahan, tetapi margin ini terlalu kecil untuk menampungnya.
Robert Harvey

Jawaban:

19

Apakah Anda benar-benar bertanya, "apakah unit test akan membantu di sini?", Atau Anda bertanya, "dapatkah segala jenis tes mungkin membantu di sini?".

Bentuk pengujian yang paling jelas yang akan membantu, adalah pernyataan prasyarat dalam kode itu sendiri, bahwa pengenal cabang hanya terdiri dari digit (seandainya ini adalah asumsi yang diandalkan oleh pembuat kode dalam menulis kode).

Ini kemudian bisa gagal dalam beberapa jenis tes integrasi, dan segera setelah id cabang alfa-numerik baru diperkenalkan maka pernyataan itu meledak. Tapi itu bukan tes unit.

Atau, mungkin ada tes integrasi dari prosedur yang menghasilkan laporan SEC. Tes ini memastikan bahwa setiap pengenal cabang nyata melaporkan transaksinya (dan oleh karena itu membutuhkan input dunia nyata, daftar semua pengidentifikasi cabang yang digunakan). Jadi itu bukan tes unit juga.

Saya tidak bisa melihat definisi atau dokumentasi dari antarmuka yang terlibat, tetapi mungkin unit test tidak mungkin mendeteksi kesalahan karena unit tidak rusak . Jika unit diizinkan untuk menganggap bahwa pengenal cabang hanya terdiri dari angka, dan pengembang tidak pernah membuat keputusan apa yang harus dilakukan kode jika tidak, maka mereka tidak bolehtulis tes unit untuk menegakkan perilaku tertentu dalam kasus pengidentifikasi non-digit karena tes tersebut akan menolak implementasi hipotetis valid unit yang menangani pengidentifikasi cabang alfanumerik dengan benar, dan Anda biasanya tidak ingin menulis tes unit yang mencegah valid implementasi dan ekstensi di masa depan. Atau mungkin satu dokumen yang ditulis 40 tahun yang lalu secara implisit didefinisikan (melalui sejumlah leksikografis dalam EBCDIC mentah, alih-alih aturan pemeriksaan yang lebih ramah-manusia) bahwa 10B adalah pengidentifikasi tes karena pada kenyataannya jatuh antara 089 dan 100. Tetapi kemudian 15 tahun yang lalu seseorang memutuskan untuk menggunakannya sebagai pengidentifikasi nyata, sehingga "kesalahan" tidak terletak pada unit yang mengimplementasikan definisi asli dengan benar: itu terletak pada proses yang gagal untuk melihat bahwa 10B didefinisikan sebagai pengidentifikasi tes dan karenanya tidak boleh ditugaskan ke cabang. Hal yang sama akan terjadi di ASCII jika Anda mendefinisikan 089 - 100 sebagai rentang tes dan kemudian memperkenalkan pengidentifikasi 10 $ atau 1,0. Kebetulan dalam EBCDIC angka datang setelah surat.

Satu unit tes (atau bisa dibilang tes fungsional) yang mungkinmungkin telah menyelamatkan hari, adalah tes unit yang menghasilkan atau memvalidasi pengidentifikasi cabang baru. Tes itu akan menyatakan bahwa pengidentifikasi harus hanya berisi digit, dan akan ditulis untuk memungkinkan pengguna pengidentifikasi cabang untuk mengasumsikan yang sama. Atau mungkin ada unit di suatu tempat yang mengimpor pengenal cabang nyata tetapi tidak pernah melihat yang menguji, dan itu bisa diuji unit untuk memastikan ia menolak semua pengidentifikasi tes (jika pengidentifikasi hanya tiga karakter kita dapat menghitung semuanya, dan membandingkan perilaku validator ke filter-tes untuk memastikan mereka cocok, yang berkaitan dengan keberatan biasa untuk tes-spot). Kemudian ketika seseorang mengubah aturan, unit test akan gagal karena bertentangan dengan perilaku yang baru diperlukan.

Karena tes ada di sana untuk alasan yang baik, titik di mana Anda perlu menghapusnya karena perubahan persyaratan bisnis menjadi peluang bagi seseorang untuk diberi pekerjaan, "temukan setiap tempat dalam kode yang bergantung pada perilaku yang ingin kita lakukan. perubahan". Tentu saja ini sulit dan karenanya tidak dapat diandalkan, sehingga tidak berarti menjamin hari itu. Tetapi jika Anda menangkap asumsi Anda dalam pengujian unit yang Anda anggap sebagai properti, maka Anda telah memberi diri Anda kesempatan dan upaya tersebut tidak sepenuhnya sia-sia.

Saya setuju tentu saja bahwa jika unit tersebut tidak didefinisikan pada awalnya dengan input "berbentuk lucu", maka tidak akan ada yang perlu diuji. Divisi namespace Fiddly mungkin sulit untuk diuji dengan benar karena kesulitannya tidak terletak pada penerapan definisi lucu Anda, itu terletak pada memastikan bahwa semua orang memahami dan menghormati definisi lucu Anda. Itu bukan properti lokal dari satu unit kode. Selain itu, mengubah beberapa tipe data dari "string digit" menjadi "string alfanumerik" mirip dengan membuat program berbasis ASCII menangani Unicode: itu tidak akan mudah jika kode Anda sangat digabungkan ke definisi asli, dan ketika tipe data sangat mendasar untuk apa yang dilakukan oleh program maka sering kali sangat digabungkan.

itu agak mengganggu untuk berpikir itu sebagian besar usaha sia-sia

Jika unit test Anda kadang gagal (saat Anda melakukan refactoring, misalnya), dan dengan melakukan hal itu memberi Anda informasi yang bermanfaat (perubahan Anda salah, misalnya), maka upaya itu tidak sia-sia. Yang tidak mereka lakukan adalah menguji apakah sistem Anda berfungsi. Jadi, jika Anda menulis tes unit alih-alih melakukan tes fungsional dan integrasi, maka Anda mungkin menggunakan waktu Anda secara kurang optimal.

Steve Jessop
sumber
Pernyataan bagus!
3
@nocomprende: seperti yang dikatakan Reagan, "percaya, tapi verifikasi".
Steve Jessop
1
Saya juga akan mengatakan "Unit test jelek!" tetapi saya pikir kebanyakan orang akan melewatkan referensi ke Peternakan Hewan dan mulai benar-benar mengkritik saya alih-alih memikirkan apa yang saya katakan (tanggapan spontan tidak efektif) tetapi saya tidak mengatakan itu. Mungkin seseorang yang lebih pintar dan memiliki pengetahuan yang lebih besar dapat menunjukkan hal itu.
2
"Semua tes lulus, tetapi beberapa tes LEBIH lulus dari yang lain!"
Graham
1
pengujian adalah herring merah. Orang-orang ini tidak tahu bagaimana "kode cabang" didefinisikan. Ini akan seperti Kantor Pos AS tidak tahu bahwa itu mengubah definisi kode pos ketika menambahkan 4 digit.
radarbob
120

Tes unit dapat menangkap bahwa kode cabang 10B dan 10C secara keliru diklasifikasikan sebagai "cabang pengujian", tetapi saya merasa tidak mungkin bahwa tes untuk klasifikasi cabang akan cukup luas untuk menangkap kesalahan itu.

Di sisi lain, pemeriksaan langsung dari laporan yang dihasilkan dapat mengungkapkan bahwa 10B dan 10C bercabang secara konsisten hilang dari laporan lebih cepat daripada 15 tahun bahwa bug sekarang dibiarkan tetap ada.

Akhirnya, ini adalah ilustrasi yang bagus mengapa itu adalah ide yang buruk untuk mencampur data pengujian dengan data produksi nyata dalam satu database. Jika mereka menggunakan database terpisah yang berisi data pengujian, tidak akan ada kebutuhan untuk menyaring yang keluar dari laporan resmi dan tidak mungkin untuk menyaring terlalu banyak.

Bart van Ingen Schenau
sumber
80
+1 Unit test tidak pernah bisa mengompensasi keputusan desain yang buruk (seperti tes pencampuran dan data nyata)
Jeutnarg
5
Meskipun yang terbaik adalah menghindari pencampuran data uji dengan data nyata, mungkin sulit untuk memvalidasi sistem produksi jika itu memerlukan modifikasi data nyata. Misalnya, ide buruk untuk memvalidasi sistem perbankan dengan memodifikasi total rekening bank dalam produksi. Menggunakan rentang kode untuk menunjuk makna merupakan masalah. Atribut catatan yang lebih eksplisit mungkin akan menjadi pilihan yang lebih baik.
JimmyJames
4
@ Oh, saya pikir ada asumsi diam-diam bahwa ada tingkat kompleksitas atau persyaratan keandalan di mana pengujian sistem produksi aktual yang digunakan dianggap berharga atau perlu. (Pertimbangkan berapa banyak yang bisa salah karena variabel konfigurasi yang salah.) Saya bisa melihat ini menjadi kasus untuk lembaga keuangan besar.
jpmc26
4
@ Oh, saya tidak berbicara tentang pengujian. Saya sedang berbicara tentang validasi sistem. Dalam sistem produksi nyata, ada banyak cara yang dapat gagal yang tidak ada hubungannya dengan kode. Jika Anda memasukkan sistem perbankan baru ke dalam produksi, Anda mungkin memiliki beberapa masalah di db atau jaringan dll. Yang mencegah transaksi dari diterapkan ke akun. Saya tidak pernah bekerja di bank, tetapi saya cukup yakin itu akan mulai memodifikasi akun riil dengan transaksi palsu. Sehingga meninggalkan Anda dengan membuat akun palsu atau menunggu dan berdoa.
JimmyJames
12
@JimmyJames Dalam layanan kesehatan, adalah umum untuk secara berkala menyalin basis data produksi ke lingkungan pengujian untuk melakukan pengujian data yang sedekat mungkin dengan kenyataan; Saya pikir bank dapat melakukan hal yang sama.
dj18
75

Perangkat lunak harus menangani aturan bisnis tertentu. Jika ada tes unit, tes unit akan memeriksa bahwa perangkat lunak menangani aturan bisnis dengan benar.

Aturan bisnis berubah.

Tampaknya tidak ada yang menyadari bahwa aturan bisnis telah berubah, dan tidak ada yang mengubah perangkat lunak untuk menerapkan aturan bisnis baru. Jika ada unit test, unit test itu harus diubah, tetapi tidak ada yang akan melakukan itu karena tidak ada yang menyadari bahwa aturan bisnis telah berubah.

Jadi tidak, unit test tidak akan menangkap itu.

Pengecualiannya adalah jika tes unit dan perangkat lunak telah dibuat oleh tim independen, dan tim yang melakukan tes unit mengubah tes untuk menerapkan aturan bisnis baru. Maka unit test akan gagal, yang diharapkan akan menghasilkan perubahan perangkat lunak.

Tentu saja dalam kasus yang sama jika hanya perangkat lunak yang diubah dan bukan unit test, maka unit test juga akan gagal. Setiap kali tes unit gagal, itu tidak berarti perangkat lunak salah, itu berarti perangkat lunak atau tes unit (kadang-kadang keduanya) salah.

gnasher729
sumber
2
Apakah layak untuk memiliki tim yang berbeda di mana seseorang mengerjakan kode dan lainnya pada tes "unit"? Bagaimana itu mungkin? ... Saya refactoring kode saya sepanjang waktu.
Sergio
2
@Sergio dari satu perspektif, refactoring mengubah internal sambil menjaga perilaku - jadi jika tes ditulis dengan cara yang menguji perilaku tanpa bergantung pada internal, maka itu tidak perlu diperbarui.
Daenyth
1
Saya telah melihat ini terjadi beberapa kali. Perangkat lunak dalam produksi tanpa keluhan, maka tiba-tiba pengguna meledak dengan keluhan bahwa itu tidak lagi berfungsi dan telah secara bertahap gagal selama bertahun-tahun. Itulah yang terjadi ketika Anda memutuskan untuk pergi dan mengubah prosedur internal Anda tanpa mengikuti proses pemberitahuan standar ...
Brian Knoblauch
42
"Aturan bisnis berubah" adalah pengamatan kritis. Tes unit memvalidasi bahwa Anda menerapkan logika yang Anda pikir telah Anda terapkan , bukan bahwa logika Anda benar .
Ryan Cavanaugh
5
Jika saya benar tentang apa yang terjadi, tidak mungkin unit test untuk mengetahui ini akan ditulis. Prinsip dasar untuk memilih tes adalah untuk menguji beberapa kasus "baik", beberapa kasus "buruk", dan kasus mengurung batas apa pun. Dalam hal ini, Anda akan menguji "099", "100", dan "101". Karena "10B" dicakup oleh tes "tolak non-angka" di bawah sistem lama, dan lebih besar dari 101 (dan juga dicakup oleh pengujian itu) di bawah sistem baru, tidak ada alasan untuk mengujinya - kecuali bahwa dalam EBCDIC, "10B" berkisar antara "099" dan "100".
Markus
29

Tidak. Ini adalah salah satu masalah besar dengan pengujian unit: mereka menidurkan Anda ke rasa aman yang salah.

Jika semua tes Anda lulus, itu tidak berarti sistem Anda berfungsi dengan baik; itu berarti semua tes Anda lulus . Ini berarti bahwa bagian-bagian dari desain Anda yang secara sadar Anda pikirkan dan tulis untuk tes bekerja sesuai dengan yang Anda pikirkan, yang sebenarnya bukan masalah besar: itu adalah hal-hal yang benar-benar Anda perhatikan. untuk, jadi sangat mungkin Anda melakukannya dengan benar! Tetapi tidak ada gunanya menangkap kasus yang tidak pernah Anda pikirkan, seperti yang ini, karena Anda tidak pernah berpikir untuk menulis tes untuk mereka. (Dan jika Anda punya, Anda akan menyadari bahwa itu berarti perubahan kode diperlukan, dan Anda akan mengubahnya.)

Mason Wheeler
sumber
17
Ayah saya sering bertanya kepada saya: Mengapa Anda tidak memikirkan hal yang tidak Anda pikirkan? (Hanya dia yang membuat ini membingungkan dengan mengatakan "Jika kamu tidak tahu, tanyakan !") Tetapi bagaimana saya tahu bahwa saya tidak tahu?
7
"Itu berarti bagian-bagian dari desainmu yang secara sadar kau pikirkan dan tuliskan untukmu bekerja sesuai dengan yang kau pikirkan." Benar sekali. Informasi ini sangat berharga jika Anda refactoring, atau jika sesuatu berubah di tempat lain dalam sistem yang merusak asumsi Anda. Pengembang yang terbuai pada rasa aman yang salah sama sekali tidak memahami keterbatasan pengujian unit, tetapi itu tidak membuat unit menguji alat yang tidak berguna.
Robert Harvey
12
@MasonWheeler: Seperti Anda, penulis berpikir bahwa pengujian unit entah bagaimana seharusnya membuktikan bahwa program Anda berfungsi. Tidak. Saya ulangi bahwa: pengujian unit tidak membuktikan bahwa program Anda berfungsi. Pengujian unit membuktikan bahwa metode Anda memenuhi kontrak pengujian Anda, dan hanya itu yang dilakukannya. Sisa kertas jatuh, karena bersandar pada premis tunggal yang tidak valid.
Robert Harvey
5
Biasanya, pengembang yang memiliki keyakinan keliru akan kecewa ketika pengujian unit benar-benar gagal, tetapi itu adalah kesalahan pengembang, bukan pengujian unit, dan itu tidak membatalkan nilai asli yang disediakan pengujian unit.
Robert Harvey
5
o_O @ kalimat pertama Anda. Tes unit memberi Anda rasa aman palsu saat melakukan koding seperti memegang tangan Anda di kemudi memberi Anda rasa aman palsu saat mengemudi.
djechlin
10

Tidak, belum tentu.

Persyaratan asli adalah untuk menggunakan kode cabang numerik, sehingga unit test akan diproduksi untuk komponen yang menerima berbagai kode dan menolak 10B. Sistem akan dianggap berfungsi (yang dulu).

Kemudian, persyaratan akan berubah dan kode diperbarui, tetapi ini berarti kode uji unit yang memasok data buruk (yang sekarang merupakan data yang baik) harus diubah.

Sekarang kita berasumsi bahwa, orang yang mengelola sistem akan mengetahui hal ini dan akan mengubah tes unit untuk menangani kode baru ... tetapi jika mereka tahu itu terjadi, mereka juga akan tahu untuk mengubah kode yang menangani ini kode tetap .. dan mereka tidak melakukan itu. Tes unit yang awalnya menolak kode 10B akan dengan senang hati mengatakan "semuanya baik-baik saja di sini" ketika dijalankan, jika Anda tidak tahu untuk memperbarui tes itu.

Pengujian unit baik untuk pengembangan asli tetapi tidak untuk pengujian sistem, terutama tidak 15 tahun setelah persyaratan lama dilupakan.

Apa yang mereka butuhkan dalam situasi semacam ini adalah tes integrasi ujung ke ujung. Satu tempat Anda bisa menyampaikan data yang Anda harapkan berfungsi dan melihat apakah itu berhasil. Seseorang akan memperhatikan bahwa data input baru mereka tidak menghasilkan laporan dan kemudian akan menyelidiki lebih lanjut.

gbjbaanb
sumber
Spot on. Dan masalah utama (hanya?) Dengan unit test. Menyelamatkan saya dengan kata-kata jawaban saya sendiri, karena saya akan mengatakan hal yang persis sama (tapi mungkin lebih buruk!) :)
Lightness Races in Orbit
8

Jenis pengujian (proses pengujian invarian menggunakan data valid yang dihasilkan secara acak, seperti dicontohkan oleh perpustakaan pengujian Haskell QuickCheck dan berbagai port / alternatif yang terinspirasi olehnya dalam bahasa lain) mungkin telah menangkap masalah ini, unit testing hampir pasti tidak akan melakukan .

Ini karena ketika aturan untuk validitas kode cabang diperbarui, tidak mungkin ada orang yang berpikir untuk menguji rentang tertentu untuk memastikan mereka bekerja dengan benar.

Namun, jika pengujian tipe telah digunakan, seseorang harus pada saat sistem asli diimplementasikan telah menulis sepasang properti, satu untuk memeriksa bahwa kode spesifik untuk cabang uji diperlakukan sebagai data uji dan satu untuk memeriksa bahwa tidak ada kode lain adalah ... ketika definisi tipe data untuk kode cabang diperbarui (yang seharusnya diperlukan untuk memungkinkan pengujian bahwa salah satu perubahan untuk kode cabang dari digit ke angka bekerja), tes ini akan mulai menguji nilai dalam kisaran baru dan kemungkinan besar akan mengidentifikasi kesalahan.

Tentu saja, QuickCheck pertama kali dikembangkan pada tahun 1999, jadi sudah terlambat untuk menangkap masalah ini.

Jules
sumber
1
Saya pikir itu lebih normal untuk menyebut pengujian berbasis properti ini, dan tentu saja mungkin saja untuk menulis tes berbasis properti yang masih akan lulus mengingat perubahan ini (meskipun saya pikir Anda lebih mungkin menulis tes yang dapat menemukannya)
jk.
5

Saya benar-benar ragu pengujian unit akan membuat perbedaan untuk masalah ini. Kedengarannya seperti salah satu situasi penglihatan terowongan karena fungsi diubah untuk mendukung kode cabang baru, tetapi ini tidak dilakukan di semua area dalam sistem.

Kami menggunakan pengujian unit untuk merancang kelas. Menjalankan kembali tes unit hanya diperlukan jika desain telah berubah. Jika unit tertentu tidak berubah, maka unit tes yang tidak berubah akan mengembalikan hasil yang sama seperti sebelumnya. Tes unit tidak akan menunjukkan kepada Anda dampak perubahan ke unit lain (jika mereka melakukannya, Anda tidak menulis tes unit).

Anda hanya dapat mendeteksi masalah ini secara wajar melalui:

  • Tes integrasi - tetapi Anda harus secara khusus menambahkan format kode baru untuk memberi makan melalui beberapa unit dalam sistem (yaitu mereka hanya akan menunjukkan masalah jika tes asli menyertakan cabang yang sekarang valid)
  • Pengujian ujung ke ujung - bisnis harus menjalankan tes ujung ke ujung yang memasukkan format kode cabang lama dan baru

Tidak memiliki pengujian end-to-end yang memadai lebih mengkhawatirkan. Anda tidak dapat mengandalkan pengujian unit karena HANYA atau tes UTAMA Anda untuk perubahan sistem. Kedengarannya seperti itu hanya diperlukan seseorang untuk menjalankan laporan pada format kode cabang yang baru didukung.

Kerangka Kelas
sumber
2

Pernyataan bawaan untuk run-time mungkin membantu; sebagai contoh:

  1. Buat fungsi seperti bool isTestOnly(string branchCode) { ... }
  2. Gunakan fungsi ini untuk memutuskan laporan mana yang akan disaring
  3. Gunakan kembali fungsi itu dalam pernyataan, dalam kode pembuatan cabang, untuk memverifikasi atau menegaskan bahwa cabang tidak (tidak dapat) dibuat menggunakan jenis kode cabang ini‼
  4. Biarkan pernyataan ini diaktifkan dalam waktu nyata (dan tidak "dioptimalkan pergi kecuali dalam versi pengembang hanya debug kode")‼

Lihat juga:

ChrisW
sumber
2

Keuntungan dari ini adalah ke Fail Fast .

Kami tidak memiliki kode, kami juga tidak memiliki banyak contoh awalan yang atau tidak menguji awalan cabang menurut kode. Yang kita miliki adalah ini:

  • 089 - 100 => cabang uji
  • 10B, 10C => cabang uji
  • <088 => mungkin cabang nyata
  • > 100 => mungkin cabang nyata

Fakta bahwa kode memungkinkan angka dan string lebih dari sedikit aneh. Tentu saja, 10B dan 10C dapat dianggap sebagai angka heksa, tetapi jika semua awalan diperlakukan sebagai angka heksa, 10B dan 10C berada di luar rentang tes dan akan diperlakukan sebagai cabang nyata.

Ini kemungkinan berarti bahwa awalan disimpan sebagai string tetapi diperlakukan sebagai angka dalam beberapa kasus. Berikut adalah kode paling sederhana yang dapat saya pikirkan yang mereplikasi perilaku ini (menggunakan C # untuk tujuan ilustrasi):

bool IsTest(string strPrefix) {
    int iPrefix;
    if(int.TryParse(strPrefix, out iPrefix))
        return iPrefix >= 89 && iPrefix <= 100;
    return true; //here is the problem
}

Dalam bahasa Inggris, jika string adalah angka dan antara 89 dan 100, itu adalah tes. Jika itu bukan angka, itu ujian. Kalau tidak, ini bukan ujian.

Jika kode mengikuti pola ini, tidak ada unit test akan menangkap ini pada saat kode itu digunakan. Berikut adalah beberapa contoh unit test:

assert.isFalse(IsTest("088"))
assert.isTrue(IsTest("089"))
assert.isTrue(IsTest("095"))
assert.isTrue(IsTest("100"))
assert.isFalse(IsTest("101"))
assert.isTrue(IsTest("10B")) // <--- business rule change

Tes unit menunjukkan bahwa "10B" harus diperlakukan sebagai cabang uji. Pengguna @ gnasher729 di atas mengatakan bahwa aturan bisnis berubah dan itulah yang ditunjukkan oleh pernyataan terakhir di atas. Pada titik tertentu yang menyatakan harus beralih ke isFalse, tetapi itu tidak terjadi. Tes unit dijalankan pada waktu pengembangan dan waktu pengembangan tetapi kemudian tidak ada titik setelahnya.


Apa pelajarannya di sini? Kode membutuhkan beberapa cara untuk memberi sinyal bahwa ia menerima input yang tidak terduga. Berikut adalah cara alternatif untuk menulis kode ini yang menekankan bahwa ia mengharapkan awalan menjadi angka:

// Alternative A
bool TryGetIsTest(string strPrefix, out bool isTest) {
    int iPrefix;
    if(int.TryParse(strPrefix, out iPrefix)) {
        isTest = iPrefix >= 89 && iPrefix <= 100;
        return true;
    }
    isTest = true; //this is just some value that won't be read
    return false;
}

Bagi mereka yang tidak tahu C #, nilai kembali menunjukkan apakah kode mampu mengurai awalan dari string yang diberikan. Jika nilai kembali benar, kode panggilan dapat menggunakan variabel isTest out untuk memeriksa apakah awalan cabang adalah awalan tes. Jika nilai kembali salah, kode panggilan harus melaporkan bahwa awalan yang diberikan tidak diharapkan, dan variabel isTest out tidak berarti dan harus diabaikan.

Jika Anda setuju dengan pengecualian, Anda dapat melakukan ini sebagai gantinya:

// Alternative B
bool IsTest(string strPrefix) {
    int iPrefix = int.Parse(strPrefix);
    return iPrefix >= 89 && iPrefix <= 100;
}

Alternatif ini lebih mudah. Dalam hal ini, kode panggilan harus menangkap pengecualian. Dalam kedua kasus, kode harus memiliki beberapa cara pelaporan kepada pemanggil bahwa itu tidak mengharapkan strPrefix yang tidak dapat dikonversi ke integer. Dengan cara ini kode gagal dengan cepat dan bank dapat dengan cepat menemukan masalah tanpa rasa malu denda SEC.

pengguna2023861
sumber
1

Begitu banyak jawaban dan bahkan kutipan Dijkstra:

Pengujian menunjukkan keberadaan, bukan tidak adanya bug.

Karena itu tergantung. Jika kode diuji dengan benar, kemungkinan besar bug ini tidak akan ada.

BЈовић
sumber
-1

Saya pikir unit test di sini akan memastikan masalah tidak pernah ada sejak awal.

Pertimbangkan, Anda telah menulis bool IsTestData(string branchCode)fungsinya.

Tes unit pertama yang Anda tulis harus untuk string nol dan kosong. Kemudian untuk string panjang yang salah maka untuk string non integer.

Untuk membuat semua tes lulus, Anda harus menambahkan pemeriksaan parameter ke fungsi.

Bahkan jika Anda hanya menguji data 'baik' 001 -> 999 tidak memikirkan kemungkinan 10A, pengecekan parameter akan memaksa Anda untuk menulis ulang fungsi saat Anda mulai menggunakan alfanumerik untuk menghindari pengecualian yang akan dilontarkannya.

Ewan
sumber
1
Ini tidak akan membantu - fungsi tidak berubah, dan tes tidak akan mulai gagal mengingat data tes yang sama. Seseorang harus berpikir untuk mengubah tes untuk membuatnya gagal, tetapi jika mereka memikirkannya, mereka mungkin akan berpikir untuk mengubah fungsinya juga.
Hulk
(Atau mungkin saya kehilangan sesuatu, karena saya tidak yakin apa yang Anda maksud dengan "pengecekan parameter")
Hulk
Fungsi ini akan dipaksa untuk melemparkan pengecualian untuk inorder string non integer untuk lulus uji unit kasus tepi sederhana. Karenanya kode produksi akan salah jika Anda mulai menggunakan kode cabang alfanumerik tanpa pemrograman khusus untuk mereka
Ewan
Tetapi bukankah fungsi tersebut telah menggunakan beberapa IsValidBranchCodefungsi untuk melakukan pemeriksaan ini? Dan fungsi ini mungkin akan diubah tanpa perlu memodifikasi IsTestData? Jadi jika Anda hanya menguji 'data bagus', tes tidak akan membantu. Tes kasus tepi harus menyertakan beberapa kode cabang yang sekarang valid (dan bukan hanya beberapa yang masih tidak valid) untuk mulai gagal.
Hulk
1
Jika centang ada di IsValidCode, sehingga fungsinya lewat tanpa pemeriksaan eksplisitnya sendiri, maka ya itu mungkin terlewatkan, tetapi kemudian kita akan memiliki serangkaian tes yang lebih banyak lagi, mengejek Validator dll, bahkan lebih banyak peluang untuk spesifik "ini adalah nomor tes "
Ewan