Apakah berguna untuk unit metode pengujian di mana logika hanya penjaga?

12

Katakanlah saya punya metode seperti ini:

public void OrderNewWidget(Widget widget)
{
   if ((widget.PartNumber > 0) && (widget.PartAvailable))
   {
        WigdetOrderingService.OrderNewWidgetAsync(widget.PartNumber);
   }
}

Saya memiliki beberapa metode seperti itu dalam kode saya (bagian depan ke panggilan Layanan Web async).

Saya berdebat apakah berguna untuk membuat mereka dilindungi dengan unit test. Ya ada logika di sini, tetapi itu hanya logika penjaga. (Artinya saya memastikan saya memiliki barang yang saya butuhkan sebelum saya mengizinkan panggilan layanan web terjadi.)

Sebagian dari saya mengatakan "yakin Anda dapat mengujinya, tetapi tidak sepadan dengan waktunya" (Saya sedang mengerjakan proyek yang sudah terlambat).

Tetapi sisi lain dari saya mengatakan, jika Anda tidak mengujinya, dan seseorang mengganti Pengawal, maka mungkin ada masalah.

Tetapi bagian pertama dari saya mengatakan kembali, jika seseorang mengganti penjaga, maka Anda hanya membuat lebih banyak pekerjaan untuk mereka (karena sekarang mereka harus mengubah penjaga dan unit tes untuk penjaga).

Misalnya, jika layanan saya memikul tanggung jawab untuk memeriksa ketersediaan Widget maka saya mungkin tidak ingin penjaga itu lagi. Jika sedang dalam uji unit, saya harus mengubah dua tempat sekarang.

Saya melihat pro dan kontra dalam kedua cara. Jadi saya pikir saya akan bertanya apa yang telah dilakukan orang lain.

Gunung berapi
sumber
17
Anda tidak membuat "lebih banyak pekerjaan" untuk pengelola. Jika mereka mengubah logika, mereka harus mengubah unit test yang sesuai. Begitulah cara kerjanya. Saya tidak melihat kontra Anda: jika pengujian unit Anda tidak perlu diubah, maka itu tidak akan menguji apa pun, bukan? Anda mungkin juga mempertanyakan apakah pengujian unit bermanfaat sama sekali.
Andres F.
9
Ini bukan topik, tapi saya akan mengubah logika untuk membuang pengecualian jika nomor bagiannya 0 atau kurang, atau jika bagian itu tidak tersedia, seperti yang menurut saya akan menjadi bug untuk memungkinkan seseorang memanggil metode itu dengan widget palsu, secara diam-diam menutupi masalah lain.
Matius
2
@ Matius poin yang sangat bagus. Fungsi ini terletak. Penamaan memberi tahu Anda itu akan memesan sesuatu. Dan kemudian tidak tetapi Anda tidak akan pernah tahu, kecuali jika Anda menerapkan logika yang sama seperti di dalam, yang iviolates KERING. Dengan kata lain: jika desain diubah menjadi lebih benar, pertanyaan ini mungkin tidak akan ditanyakan sejak awal.
stijn
2
but it is not worth the time" (I am on a project that is already behind schedule).Kami adalah pengembang perangkat lunak. Satu-satunya waktu kami sesuai jadwal adalah ketika kami mati :)
maple_shaft

Jawaban:

26

Sebagian dari saya mengatakan "yakin Anda dapat mengujinya, tetapi tidak sepadan dengan waktunya" (Saya sedang mengerjakan proyek yang sudah terlambat).

Ini tiga tes yang sangat singkat. Anda menghabiskan banyak waktu bertanya pada diri sendiri pertanyaan itu.

Tetapi sisi lain dari saya mengatakan, jika Anda tidak mengujinya, dan seseorang mengganti Pengawal, maka mungkin ada masalah.

Dengarkan sisi ini.

Tetapi bagian pertama dari saya mengatakan kembali, jika seseorang mengganti penjaga, maka Anda hanya membuat lebih banyak pekerjaan untuk mereka (karena sekarang mereka harus mengubah penjaga dan unit tes untuk penjaga).

Jika pemelihara Anda adalah kacang TDD, Anda membuatnya lebih sulit untuk mereka. Setiap perubahan yang saya lakukan tanpa ada perubahan terkait atau penambahan tes menyebabkan saya harus berpikir keras. Bahkan, saya mungkin akan menambahkan tes sebelum saya melanjutkan dan membuat perubahan.

Bagian pertama dari Anda benar-benar salah. Berikan tepukan pada bagian kedua dan berhenti memikirkannya.

pdr
sumber
+1 untuk ringkasnya meskipun saya menulis jawaban juga heh
Jimmy Hoffa
3
+1. Ya, jika persyaratannya berubah, beberapa tes harus disesuaikan.
Olivier Jacot-Descombes
Sementara saya menyukai apa yang Anda katakan, saya memiliki banyak contoh panggilan semacam ini dalam kode saya (bagian depan dari panggilan async). Jadi bukan hanya 3 unit tes. Namun, jika itu adalah cara yang "benar" maka saya ingin menyelesaikannya.
Vaccano
@ Vacano: Semakin banyak yang harus Anda tulis, semakin banyak jalur logis yang tidak perlu Anda uji dan semakin perlu untuk menulisnya.
pdr
9

Ini akan menyederhanakan pengujian unit jika logika penjaga dan pemesanan aktual adalah metode yang terpisah.

Di Widgetkelas

public bool IsReadyForOrdering { get { return PartNumber > 0 && PartAvailable; } }

atau metode yang setara di tempat lain

public bool IsWidgetReadyForOrdering(Widget widget)
{
    return widget.PartNumber > 0 && widget.PartAvailable;
}

Metode pemesanan

public void OrderNewWidget(Widget widget)
{
   if (IsWidgetReadyForOrdering(widget)) {
        WigdetOrderingService.OrderNewWidgetAsync(widget.PartNumber);
   }
}

Sekarang pengujian IsWidgetReadyForOrderingmenjadi mudah. Jangan berpikir lama tentang itu lagi. Menguji!

Olivier Jacot-Descombes
sumber
1
Ya, logika stateful dalam properti .. -1 yang seharusnya menjadi metode dan harus mengambil PartNumber, PartAvailable karena kesederhanaannya. Buat itu terlindungi jika tidak perlu menjadi bagian dari API publik tetapi bukan properti .. Juga saya biasanya tidak setuju. Logika penjaga di dalam metode ini benar-benar baik-baik saja, dan di mata saya lebih baik karena metode yang sangat kecil Anda hanya mencemari kelas untuk membuat metode yang sudah kecil menjadi lebih kecil. Tambahkan ke kelas dalam kasus ini hanya jika itu logika berulang.
Jimmy Hoffa
1
Pertama, ini tidak menjawab pertanyaan. Kedua, ini tidak benar. Anda harus menulis tiga tes. Ketiga, mengekspos detail implementasi ke kode panggilan, tidak perlu.
pdr
8
@JimmyHoffa: di mana Anda melihat logika stateful di properti itu? Bahkan, contoh menunjukkan bagaimana memisahkan logika yang mengubah keadaan (OrderNewWidget) dari logika non-statechanging (ReadyForOrdering). Dan saya sangat percaya bahwa mengekstraksi bahkan fungsi kecil itu akan meningkatkan kode, dan tidak membuatnya lebih buruk, seperti yang Anda nyatakan. Jadi +1.
Doc Brown
2
Metode OrderNewWidgetini mungkin berada di kelas lain daripada Widget, karena memiliki Widgetargumen. Karena metode ini tidak memiliki nilai balik, pengujian tidak jelas. Anda harus menyuntikkan WigdetOrderingService-mock yang melacak OrderNewWidgetAsyncpanggilan.
Olivier Jacot-Descombes
2
@JimmyHoffa: sebenarnya, definisi Anda tentang "stateless" berarti "statis" dalam C #. Jadi, apa yang Anda katakan adalah "properti tidak boleh mengakses keadaan objek". Tetapi bahkan getter getol mengakses variabel status, sehingga itu berarti "hanya menulis properti statis" - yang sepertinya tidak masuk akal.
Doc Brown
6

Jika Anda tidak punya waktu dalam jadwal Anda untuk pengujian unit tetapi Anda punya waktu menyisihkan untuk penggunaan QA yang solid, maka tanyakan apakah Anda dapat mencuri waktu QA itu untuk menulis tes unit, atau jika Anda dapat menghabiskan beberapa periode QA melakukan tes unit, atau mungkin hanya berurusan dengan kode non-unit yang diuji .. Sayangnya jadwal yang tidak bergerak memaksa Anda untuk membuat konsesi atau bekerja sendiri sampai mati, saya biasanya menyarankan opsi pertama karena yang kedua akan mengakibatkan Anda tidak mampu mendukung / memelihara sistem dengan benar untuk jangka waktu itu.

Yang mengatakan, untuk pertanyaan umum Anda menguji pernyataan penjaga; Iya! Benar-benar menguji pernyataan penjaga! Itu adalah bagian penting dari perilaku metode itu, Anda tidak ingin mengetahui ada orang yang salah paham melakukan perbaikan bug dan menghilangkan penjaga Anda atau mengubahnya &&menjadi, bukan ||? Tes unit akan memastikan bahwa a) Anda benar-benar mendapatkan logika pada penjaga Anda dengan benar dan b) tidak ada yang mematahkan logika itu nanti tanpa mendapatkan keluhan ketika mereka menjalankan tes unit yang mengatakan kepada mereka bahwa itu harus seperti itu karena suatu alasan.

Jimmy Hoffa
sumber
0

Ada beberapa jawaban yang sangat baik di atas, dan poin yang mereka buat sangat penting. Tetapi satu yang tampaknya terlewatkan adalah bahwa Anda memiliki serangkaian unit test yang komprehensif, mereka membaca seperti spesifikasi kode yang sangat terperinci. Jika Anda mengabaikan validasi pengujian hanya karena kodenya begitu mudah, sulit untuk melihat bagaimana kesalahannya, bagian dari spesifikasi Anda tidak ada. Jika saya datang ke tim di mana tes-tes ini terlewatkan, saya benar-benar akan menganggap layanan Anda tidak memvalidasi argumennya.

Jules
sumber
-5

Kode adalah kode. Anda harus mencoba untuk mendapatkan cakupan 100% saat pengujian. Jika tidak penting itu tidak akan ada di sana.

Pengguna Super
sumber