Menulis kode minimum untuk lulus tes unit - tanpa curang!

36

Ketika melakukan TDD dan menulis unit test, bagaimana seseorang menahan keinginan untuk "menipu" ketika menulis iterasi pertama dari kode "implementasi" yang Anda uji?

Sebagai contoh:
Mari saya perlu menghitung faktorial suatu angka. Saya mulai dengan tes unit (menggunakan MSTest) sesuatu seperti:

[TestClass]
public class CalculateFactorialTests
{
    [TestMethod]
    public void CalculateFactorial_5_input_returns_120()
    {
        // Arrange
        var myMath = new MyMath();
        // Act
        long output = myMath.CalculateFactorial(5);
        // Assert
        Assert.AreEqual(120, output);
    }
}

Saya menjalankan kode ini, dan gagal karena CalculateFactorialmetode ini bahkan tidak ada. Jadi, saya sekarang menulis iterasi pertama dari kode untuk mengimplementasikan metode yang diuji, menulis kode minimum yang diperlukan untuk lulus tes.

Masalahnya, saya terus tergoda untuk menulis yang berikut ini:

public class MyMath
{
    public long CalculateFactorial(long input)
    {
        return 120;
    }
}

Hal ini, secara teknis, benar bahwa itu benar-benar adalah kode minimum yang diperlukan untuk membuat tes khusus lulus (go green), meskipun jelas "menipu" karena benar-benar bahkan tidak berusaha untuk melakukan fungsi menghitung faktorial. Tentu saja, sekarang bagian refactoring menjadi latihan dalam "menulis fungsionalitas yang benar" daripada refactoring sejati implementasi. Jelas, menambahkan tes tambahan dengan parameter yang berbeda akan gagal dan memaksa refactoring, tetapi Anda harus mulai dengan satu tes itu.

Jadi, pertanyaan saya adalah, bagaimana Anda mendapatkan keseimbangan antara "menulis kode minimum untuk lulus tes" sambil tetap berfungsi dan dalam semangat apa yang sebenarnya Anda coba capai?

CraigTP
sumber
4
Itu adalah hal yang manusiawi: Anda harus menahan keinginan untuk menipu. Tidak ada yang lebih dari itu. Anda bisa menambahkan lebih banyak tes dan menulis lebih banyak kode uji daripada kode untuk diuji, tetapi jika Anda tidak memiliki kemewahan itu, Anda hanya perlu menolaknya. Ada banyak BANYAK tempat dalam pengkodean di mana kita harus menahan keinginan untuk meretas atau menipu, karena kita tahu bahwa, sementara itu mungkin bekerja hari ini, itu tidak akan berfungsi nanti.
Dan Rosenstark
7
Tentunya, dalam TDD, melakukannya sebaliknya adalah curang - yaitu mengembalikan 120 adalah cara yang tepat. Saya merasa cukup sulit untuk membuat diri saya melakukan itu, dan tidak berpacu ke depan dan mulai menulis perhitungan faktorial.
Paul Butcher
2
Saya akan menganggap ini sebagai cheat, hanya karena itu dapat lulus tes tetapi tidak menambah fungsionalitas yang sebenarnya atau membuat Anda lebih dekat ke solusi akhir untuk masalah yang dihadapi.
GrumpyMonkey
3
Jika ternyata kode kode klien hanya pernah lulus dalam 5, mengembalikan 120 bukan hanya bukan cheat, tetapi sebenarnya solusi yang sah.
Kramii Reinstate Monica
Saya setuju dengan @PaulButcher - pada kenyataannya, banyak contoh pengujian unit dalam teks dan artikel akan mengambil pendekatan ini.
HorusKol

Jawaban:

45

Ini sangat sah. Merah, Hijau, Refactor.

Tes pertama berlalu.

Tambahkan tes kedua, dengan input baru.

Sekarang dengan cepat menjadi hijau, Anda bisa menambahkan if-else, yang berfungsi dengan baik. Itu berlalu, tetapi Anda belum selesai.

Bagian ketiga dari Red, Green, Refactor adalah yang paling penting. Refactor untuk menghapus duplikasi . Anda AKAN memiliki duplikasi dalam kode Anda sekarang. Dua pernyataan mengembalikan bilangan bulat. Dan satu-satunya cara untuk menghapus duplikasi itu adalah dengan mengkodekan fungsi dengan benar.

Saya tidak mengatakan jangan menuliskannya dengan benar pertama kali. Saya hanya mengatakan itu tidak curang jika Anda tidak.

CaffGeek
sumber
12
Ini hanya menimbulkan pertanyaan, mengapa tidak hanya menulis fungsi dengan benar?
Robert Harvey
8
@ Robert, angka faktorial sederhana saja. Keuntungan sebenarnya dari TDD adalah ketika Anda menulis pustaka non-sepele, dan menulis tes pertama memaksa Anda untuk merancang API sebelum implementasi, yang - dalam pengalaman saya - mengarah ke kode yang lebih baik.
1
@ Robert, Andalah yang peduli untuk menyelesaikan masalah alih-alih lulus ujian. Saya memberi tahu Anda bahwa untuk masalah non-sepele itu hanya bekerja lebih baik untuk menunda desain keras sampai Anda memiliki tes di tempat.
1
@ Thorbjørn Ravn Andersen, tidak, saya tidak mengatakan Anda hanya dapat memiliki satu pengembalian. Ada alasan yang sah untuk banyak (yaitu, pernyataan penjaga). Masalahnya adalah, kedua pernyataan pengembalian itu "sama". Mereka melakukan 'hal' yang sama. Kebetulan mereka memiliki nilai yang berbeda. TDD bukan tentang kekakuan, dan mematuhi ukuran rasio uji / kode tertentu. Ini tentang menciptakan tingkat kenyamanan dalam basis kode Anda. Jika Anda dapat menulis tes gagal, maka fungsi yang akan bekerja untuk tes fungsi itu di masa depan, bagus. Lakukan, lalu tulis uji tepi Anda untuk memastikan fungsi Anda tetap berfungsi.
CaffGeek
3
inti dari tidak menulis implementasi penuh (walaupun sederhana) sekaligus adalah bahwa Anda tidak memiliki jaminan sama sekali bahwa tes Anda bahkan BISA gagal. titik melihat tes gagal sebelum lulus adalah bahwa Anda kemudian memiliki bukti aktual bahwa perubahan Anda pada kode adalah apa yang memuaskan pernyataan yang Anda buat di atasnya. ini adalah satu-satunya alasan mengapa TDD sangat bagus untuk membangun suite uji regresi dan benar-benar menyapu lantai dengan "tes setelah" pendekatan dalam arti itu.
sara
25

Diperlukan pemahaman yang jelas tentang tujuan akhir, dan pencapaian algoritma yang memenuhi tujuan tersebut.

TDD bukan peluru ajaib untuk desain; Anda masih harus tahu cara menyelesaikan masalah menggunakan kode, dan Anda masih harus tahu cara melakukannya pada tingkat yang lebih tinggi dari beberapa baris kode untuk membuat tes lulus.

Saya suka ide TDD karena mendorong desain yang bagus; itu membuat Anda berpikir tentang bagaimana Anda dapat menulis kode Anda sehingga dapat diuji, dan secara umum filosofi itu akan mendorong kode menuju desain yang lebih baik secara keseluruhan. Tetapi Anda masih harus tahu cara merancang solusi.

Saya tidak menyukai filosofi TDD reduksionis yang mengklaim Anda dapat mengembangkan aplikasi hanya dengan menulis kode dalam jumlah terkecil untuk lulus ujian. Tanpa memikirkan arsitektur, ini tidak akan berhasil, dan contoh Anda membuktikannya.

Paman Bob Martin mengatakan ini:

Jika Anda tidak melakukan Test Driven Development, sangat sulit menyebut diri Anda seorang profesional. Jim Coplin memanggil saya di karpet untuk yang ini. Dia tidak suka aku mengatakan itu. Faktanya, posisinya saat ini adalah bahwa Test Driven Development sedang menghancurkan arsitektur karena orang-orang menulis tes untuk mengabaikan segala jenis pemikiran lain dan merobek arsitektur mereka terpisah dalam kesibukan gila-gilaan untuk mendapatkan tes untuk lulus dan dia punya poin menarik, itu cara yang menarik untuk menyalahgunakan ritual dan kehilangan niat di balik disiplin.

jika Anda tidak memikirkan arsitektur, jika yang Anda lakukan adalah mengabaikan arsitektur dan melakukan tes bersama dan membuat mereka lulus, Anda menghancurkan hal yang akan membuat bangunan tetap terjaga karena konsentrasi pada struktur sistem dan keputusan desain yang solid yang membantu sistem mempertahankan integritas strukturalnya.

Anda tidak bisa begitu saja melempar sejumlah besar tes bersama dan membuatnya lulus selama beberapa dekade demi dekade dan menganggap bahwa sistem Anda akan bertahan. Kami tidak ingin mengubah diri kami menjadi neraka. Jadi pengembang yang didorong oleh pengujian yang baik selalu sadar untuk membuat keputusan arsitektur, selalu memikirkan gambaran besarnya.

Robert Harvey
sumber
Tidak benar-benar jawaban untuk pertanyaan itu, tetapi 1+
Tidak ada yang
2
@ rmx: Um, pertanyaannya adalah: Bagaimana Anda mendapatkan keseimbangan antara "menulis kode minimum untuk lulus tes" sementara tetap menjaganya agar tetap fungsional dan dalam semangat apa yang sebenarnya Anda coba capai? Apakah kita membaca pertanyaan yang sama?
Robert Harvey
Solusi ideal adalah algoritma dan tidak ada hubungannya dengan arsitektur. Melakukan TDD tidak akan membuat Anda menemukan algoritma. Pada titik tertentu Anda perlu membuat langkah-langkah dalam hal algoritma / solusi.
Joppe
Saya setuju dengan @rmx. Ini tidak benar-benar menjawab pertanyaan spesifik saya, tapi itu memang memunculkan pemikiran tentang bagaimana TDD secara umum cocok dengan gambaran besar dari keseluruhan proses pengembangan perangkat lunak. Jadi, untuk alasan itu, +1.
CraigTP
Saya pikir Anda bisa mengganti "algoritma" - dan istilah lain - untuk "arsitektur" dan argumen masih berlaku; ini semua tentang tidak bisa melihat kayu untuk pohon. Kecuali jika Anda akan menulis tes terpisah untuk setiap input integer tunggal, TDD tidak akan dapat membedakan antara implementasi faktorial yang tepat dan beberapa hard-coding yang bekerja untuk semua kasus yang diuji tetapi tidak untuk yang lain. Masalah dengan TDD adalah kemudahan yang "semua tes lulus" dan "kodenya bagus" digabungkan. Pada titik tertentu, ukuran yang masuk akal perlu diterapkan.
Julia Hayward
16

Pertanyaan yang sangat bagus ... dan saya harus tidak setuju dengan hampir semua orang kecuali @Robert.

Penulisan

return 120;

untuk fungsi faktorial untuk membuat satu tes lulus adalah buang - buang waktu . Itu bukan "curang", juga tidak mengikuti red-green-refactor secara harfiah. Itu salah .

Inilah alasannya:

  • Calculate Factorial adalah fitur, bukan "mengembalikan konstanta". "return 120" bukan perhitungan.
  • argumen 'refactor' salah arah; jika Anda memiliki dua test case untuk 5 dan 6, kode ini masih salah, karena Anda tidak menghitung faktorial sama sekali :

    if (input == 5) { return 120; } //input=5 case
    else { return 720; }   //input=6 case
    
  • jika kita mengikuti argumen 'refactor' secara harfiah , maka ketika kita memiliki 5 kasus uji, kita akan memanggil YAGNI dan mengimplementasikan fungsinya menggunakan tabel pencarian:

    if (factorialDictionary.Contains(input)) {
        return factorialDictionary[input]; 
    }
    throw new Exception("Input failure");
    

Tidak ada yang benar-benar menghitung apa pun, Anda . Dan itu bukan tugasnya!

Steven A. Lowe
sumber
1
@ rmx: tidak, tidak ketinggalan; "refactor untuk menghapus duplikasi" dapat dipenuhi dengan tabel pencarian. BTW prinsip bahwa tes unit menyandikan persyaratan tidak spesifik untuk BDD, itu adalah prinsip umum Agile / XP. Jika persyaratannya adalah "Jawab pertanyaan 'apa faktorial dari 5'" maka 'kembalikan 120;' akan menjadi sah ;-)
Steven A. Lowe
2
@Chad yang semuanya adalah pekerjaan yang tidak perlu - cukup tulis fungsi pertama kali ;-)
Steven A. Lowe
2
@ Seven A.Lowe, dengan logika itu, mengapa menulis tes apa pun ?! "Cukup tulis aplikasi itu pertama kali!" Titik TDD, adalah perubahan kecil, aman, tambahan.
CaffGeek
1
@Chad: strawman.
Steven A. Lowe
2
inti dari tidak menulis implementasi penuh (walaupun sederhana) sekaligus adalah bahwa Anda tidak memiliki jaminan sama sekali bahwa tes Anda bahkan BISA gagal. titik melihat tes gagal sebelum lulus adalah bahwa Anda kemudian memiliki bukti aktual bahwa perubahan Anda pada kode adalah apa yang memuaskan pernyataan yang Anda buat di atasnya. ini adalah satu-satunya alasan mengapa TDD sangat bagus untuk membangun suite uji regresi dan benar-benar menyapu lantai dengan "tes setelah" pendekatan dalam arti itu. Anda tidak pernah secara tidak sengaja menulis ujian yang tidak dapat gagal. juga, lihatlah paman bobs prime factor kata.
sara
10

Saat Anda hanya menulis satu pengujian unit, implementasi satu baris ( return 120;) adalah sah. Menulis loop menghitung nilai 120 - itu akan curang!

Tes awal yang sederhana seperti itu adalah cara yang baik untuk menangkap kasus tepi dan mencegah kesalahan satu kali. Lima sebenarnya bukan nilai input yang akan saya mulai.

Aturan praktis yang dapat berguna di sini adalah: nol, satu, banyak, banyak . Nol dan satu adalah kasus tepi penting untuk faktorial. Mereka dapat diimplementasikan dengan satu garis. Kasing uji "banyak" (mis. 5!) Kemudian akan memaksa Anda untuk menulis loop. Kasing uji "lot" (1000 !?) dapat memaksa Anda untuk mengimplementasikan algoritma alternatif untuk menangani angka yang sangat besar.

azheglov
sumber
2
Kasus "-1" akan menarik. Karena itu tidak terdefinisi dengan baik, sehingga pria yang menulis tes dan pria yang menulis kode harus menyetujui terlebih dahulu apa yang harus terjadi.
gnasher729
2
+1 untuk benar-benar menunjukkan itu factorial(5)adalah tes pertama yang buruk. kita mulai dari kasus yang paling sederhana dan dalam setiap iterasi kita membuat tes sedikit lebih spesifik, mendesak kode untuk menjadi sedikit lebih umum. inilah yang disebut paman bob sebagai premis prioritas transformasi ( blog.8thlight.com/uncle-bob/2013/05/27/… )
sara
5

Selama Anda hanya memiliki satu tes, maka kode minimal yang diperlukan untuk lulus tes benar-benar return 120;, dan Anda dapat dengan mudah mempertahankannya selama Anda tidak memiliki tes lagi.

Ini memungkinkan Anda untuk menunda desain lebih lanjut sampai Anda benar-benar menulis tes yang menggunakan nilai pengembalian LAIN dari metode ini.

Harap diingat bahwa tes adalah versi runnable spesifikasi Anda, dan jika semua itu spesifikasi mengatakan bahwa f (6) = 120 maka yang cocok dengan tagihan sempurna.


sumber
Serius? Dengan logika ini, Anda harus menulis ulang kode setiap kali seseorang membuat input baru.
Robert Harvey
6
@ Robert, pada BEBERAPA titik menambahkan kasus baru tidak akan menghasilkan kode sesederhana mungkin lagi, pada titik mana Anda menulis implementasi baru. Karena Anda sudah memiliki tes di tempat, Anda tahu persis kapan implementasi baru Anda melakukan hal yang sama dengan yang lama.
1
@ Thorbjørn Ravn Andersen, tepatnya, bagian terpenting dari Red-Green-Refactor, adalah refactoring.
CaffGeek
+1: Ini adalah ide umum dari pengetahuan saya juga, tetapi sesuatu perlu dikatakan tentang memenuhi kontrak yang tersirat (yaitu nama metode faktorial ). Jika Anda hanya spec (uji) f (6) = 120 maka Anda hanya perlu 'mengembalikan 120'. Setelah Anda mulai menambahkan tes untuk memastikan bahwa f (x) == x * x-1 ... * xx-1: upperBound> = x> = 0 maka Anda akan sampai pada fungsi yang memenuhi persamaan faktorial.
Steven Evers
1
@SnOrfus, tempat untuk "kontrak tersirat" adalah dalam kasus uji. Jika kontrak Anda adalah untuk faktorial, Anda TEST jika faktorial yang diketahui adalah dan jika non-faktorial diketahui tidak. Banyak dari mereka. Tidak perlu waktu lama untuk mengonversi daftar sepuluh faktorial pertama menjadi for-loop yang menguji setiap angka hingga faktorial kesepuluh.
4

Jika Anda dapat "menipu" sedemikian rupa, itu menunjukkan bahwa tes unit Anda cacat.

Alih-alih menguji metode faktorial dengan nilai tunggal, uji itu adalah rentang nilai. Pengujian berbasis data dapat membantu di sini.

Lihat tes unit Anda sebagai manifestasi dari persyaratan - mereka harus secara kolektif menentukan perilaku metode yang mereka uji. (Ini dikenal sebagai pengembangan yang didorong oleh perilaku - ini adalah masa depan ;-))

Jadi tanyakan pada diri Anda - jika seseorang mengubah implementasi menjadi sesuatu yang salah, apakah tes Anda akan tetap lulus atau akankah mereka berkata "tunggu sebentar!"?

Mengingat hal itu, jika hanya tes Anda yang ada di pertanyaan Anda, maka secara teknis, implementasi yang sesuai sudah benar. Masalahnya kemudian dilihat sebagai persyaratan yang tidak didefinisikan dengan baik.

Tak seorangpun
sumber
Seperti yang ditunjukkan nanda, Anda selalu dapat menambahkan serangkaian casepernyataan tanpa akhir ke switch, dan Anda tidak dapat menulis tes untuk setiap input dan output yang mungkin untuk contoh OP.
Robert Harvey
Anda dapat secara teknis menguji nilai dari Int64.MinValuehingga Int64.MaxValue. Butuh waktu lama untuk menjalankan tetapi secara eksplisit akan menentukan persyaratan tanpa ruang untuk kesalahan. Dengan teknologi saat ini, ini tidak mungkin (saya menduga bahwa itu akan menjadi lebih umum di masa depan) dan saya setuju, Anda bisa menipu tetapi saya pikir pertanyaan OPs itu tidak praktis (tidak ada yang benar-benar akan menipu dengan cara seperti itu) dalam praktek), tetapi yang teoretis.
Tidak ada yang
@ rmx: Jika Anda bisa melakukannya, tes akan menjadi algoritma, dan Anda tidak perlu lagi menulis algoritma.
Robert Harvey
Itu benar. Tesis universitas saya sebenarnya melibatkan generasi otomatis dari implementasi menggunakan unit-tes sebagai panduan dengan algoritma genetika sebagai bantuan untuk TDD - dan itu hanya mungkin dengan tes solid. Perbedaannya adalah bahwa mengikat persyaratan Anda ke kode Anda biasanya jauh lebih sulit untuk dibaca dan dipahami daripada metode tunggal yang mewujudkan tes unit. Kemudian muncul pertanyaan: jika implementasi Anda adalah manifestasi dari tes unit Anda, dan tes unit Anda adalah manifestasi dari persyaratan Anda, mengapa tidak melewatkan pengujian sama sekali? Saya tidak punya jawaban.
Tidak ada yang
Juga, bukankah kita, sebagai manusia, sama-sama membuat kesalahan dalam unit-test seperti halnya kita dalam kode implementasi? Jadi mengapa unit test?
Tidak ada yang
3

Cukup tulis lebih banyak tes. Akhirnya, itu akan terjadi pendek untuk menulis

public long CalculateFactorial(long input)
{
    return input <= 1 ? 1 : CalculateFactorial(input-1)*input;
}

dari

public long CalculateFactorial(long input)
{
    switch (input) {
       case 0: return 1;
       case 1: return 1;
       case 2: return 2;
       case 3: return 6;
       case 4: return 24;
       case 5: return 120;
    }
}

:-)

P Shved
sumber
3
Mengapa tidak hanya menulis algoritma dengan benar?
Robert Harvey
3
@ Robert, itu adalah yang algoritma yang benar untuk menghitung faktorial nomor dari 0 sampai 5. Selain itu, apa yang "benar" berarti? Ini adalah contoh yang sangat sederhana, tetapi ketika itu menjadi lebih kompleks, ada banyak gradasi dari arti "benar". Apakah program yang memerlukan akses root "cukup" cukup? Apakah menggunakan XML "benar", alih-alih menggunakan CSV? Anda tidak bisa menjawab ini. Algoritma apa pun benar selama memenuhi beberapa persyaratan bisnis, yang dirumuskan sebagai pengujian dalam TDD.
P Shved
3
Perlu dicatat bahwa karena tipe keluarannya panjang, maka hanya ada sedikit nilai input (20 atau lebih) yang fungsinya mungkin dapat ditangani dengan benar, oleh karena itu pernyataan switch yang besar belum tentu merupakan implementasi terburuk - jika kecepatan lebih penting daripada ukuran kode, pernyataan peralihan mungkin merupakan cara yang harus dilakukan, tergantung pada prioritas Anda.
user281377
3

Menulis tes "cheat" adalah OK, untuk nilai "OK" yang cukup kecil. Tetapi recall - unit testing hanya selesai ketika semua tes lulus dan tidak ada tes baru yang dapat ditulis yang akan gagal . Jika Anda benar-benar ingin memiliki metode CalculateFactorial yang berisi banyak pernyataan if (atau bahkan lebih baik, pernyataan switch / case besar :-) Anda bisa melakukan itu, dan karena Anda berurusan dengan angka presisi-tetap, kode yang diperlukan untuk mengimplementasikan ini terbatas (walaupun mungkin agak besar dan jelek, dan mungkin dibatasi oleh kompiler atau keterbatasan sistem pada ukuran maksimum kode prosedur). Pada titik ini jika Anda benar-benarbersikeras bahwa semua pengembangan harus didorong oleh tes unit Anda dapat menulis tes yang membutuhkan kode untuk menghitung hasil dalam jumlah waktu yang lebih pendek daripada yang dapat dicapai dengan mengikuti semua cabang dari pernyataan if .

Pada dasarnya, TDD dapat membantu Anda menulis kode yang mengimplementasikan persyaratan dengan benar , tetapi itu tidak dapat memaksa Anda untuk menulis kode yang baik . Terserah kamu.

Bagikan dan nikmati.

Bob Jarvis - Pasang kembali Monica
sumber
+1 untuk "pengujian unit hanya selesai ketika semua tes lulus dan tidak ada tes baru dapat ditulis yang akan gagal" Banyak orang mengatakan itu sah untuk mengembalikan konstanta, tetapi jangan ikuti dengan "untuk jangka pendek", atau " jika persyaratan keseluruhan hanya memerlukan kasus khusus "
Thymine
1

Saya 100% setuju dengan saran Robert Harveys di sini, ini bukan hanya tentang membuat tes lulus, Anda perlu mengingat tujuan keseluruhan juga.

Sebagai solusi untuk titik rasa sakit Anda dari "itu hanya diverifikasi untuk bekerja dengan set input yang diberikan" Saya akan mengusulkan menggunakan tes didorong data, seperti teori xunit. Kekuatan di balik konsep ini adalah memungkinkan Anda untuk dengan mudah membuat Spesifikasi input ke output.

Untuk faktorial, tes akan terlihat seperti ini:

    [Theory]
    [InlineData(0, 1)]
    [InlineData( 1, 1 )]
    [InlineData( 2, 2 )]
    [InlineData( 3, 6 )]
    [InlineData( 4, 24 )]
    public void Test_Factorial(int input, int expected)
    {
        int result = Factorial( input );
        Assert.Equal( result, expected);
    }

Anda bahkan bisa mengimplementasikan data uji yang menyediakan (yang mengembalikan IEnumerable<Tuple<xxx>>) dan menyandikan invarian matematis, seperti berulang kali membagi dengan n akan menghasilkan n-1).

Saya menemukan ini menjadi cara pengujian yang sangat kuat.

Johannes Rudolph
sumber
1

Jika Anda masih bisa menipu maka tes tidak cukup. Tulis lebih banyak tes! Sebagai contoh Anda, saya akan mencoba menambahkan tes dengan input 1, -1, -1000, 0, 10, 200.

Namun demikian, jika Anda benar-benar berkomitmen untuk menipu, Anda dapat menulis if-then yang tak ada habisnya. Dalam hal ini, tidak ada yang bisa membantu kecuali tinjauan kode. Anda akan segera tertangkap pada tes penerimaan ( ditulis oleh orang lain! )

Masalah dengan tes unit kadang-kadang programmer melihatnya sebagai pekerjaan yang tidak perlu. Cara yang benar untuk melihatnya adalah sebagai alat bagi Anda untuk membuat hasil pekerjaan Anda benar. Jadi jika Anda membuat if-then, Anda tahu secara tidak sadar bahwa ada kasus lain yang perlu dipertimbangkan. Ini berarti Anda harus menulis tes lain. Dan seterusnya dan seterusnya sampai Anda menyadari bahwa kecurangan tidak berfungsi dan lebih baik hanya kode cara yang benar. Jika Anda masih merasa bahwa Anda belum selesai, Anda belum selesai.

nanda
sumber
1
Jadi sepertinya Anda mengatakan bahwa hanya menulis kode yang cukup untuk lulus ujian (sebagai pendukung TDD) tidak cukup. Anda juga harus mengingat prinsip-prinsip desain perangkat lunak yang sehat. Saya setuju dengan Anda BTW.
Robert Harvey
0

Saya akan menyarankan bahwa pilihan tes Anda bukan tes terbaik.

Saya akan memulai dengan:

faktorial (1) sebagai tes pertama,

faktorial (0) sebagai yang kedua

faktorial (-ve) sebagai yang ketiga

dan kemudian melanjutkan dengan kasus-kasus non-sepele

dan selesaikan dengan case overflow.

Chris Cudmore
sumber
Apa -ve??
Robert Harvey
nilai negatif.
Chris Cudmore