TDD'ye “gerçek” kodu ne zaman yazıyorsunuz?


147

Eğitim videolarında okuduğum ve gördüğüm tüm örneklerin basit örnekleri var. Ama yeşilleştikten sonra "gerçek" kodu nasıl yapıp yapmadığımı göremiyorum. Bu "Refactor" kısmı mı?

Eğer karmaşık bir metotla oldukça karmaşık bir nesneye sahipsem ve testimi ve minimum seviyesini geçmesi için çıplak olarak yazarım (ilk başarısız olduktan sonra, Kırmızı). Ne zaman geri dönüp gerçek kodu yazacağım? Ve tekrar test etmeden önce ne kadar gerçek kod yazarım? Sanırım sonuncunun daha sezgi olduğunu düşünüyorum.

Düzenleme: Yanıtlayan herkese teşekkürler. Tüm cevapların bana çok yardımcı oldu. Ne sorduğum ya da kafamın karıştığı hakkında farklı fikirler var gibi görünüyor ve belki de var, ama sorduğum şey, okul yapmak için bir başvurum olduğunu söylüyordu.

Tasarımımda, başlamak istediğim bir mimariye sahibim, Kullanıcı Hikayeleri, vb. Buradan, Kullanıcı Hikayelerini alıyorum ve Kullanıcı Hikayesini test etmek için bir test oluşturuyorum. Kullanıcı diyor ki, bizler okula kayıt olan ve kayıt ücreti ödeyen insanlar var. Bu yüzden başarısızlığa uğramanın bir yolunu düşünüyorum. Bunu yaparken, X sınıfı (belki Öğrenci) için başarısız olacak bir test sınıfı tasarlarım. Daha sonra "Öğrenci" sınıfını yarattım. Belki "Okul" bilmiyorum.

Ancak, her durumda, TD Tasarım beni hikaye boyunca düşünmeye zorluyor. Eğer bir testi başarısız yapabilirsem, neden başarısız olduğunu biliyorum, ama bu benim önemsememeyi şart koşuyor. Bu tasarım hakkında.

Bunu Recursion hakkında düşünmekten hoşlanıyorum. Özyineleme zor bir kavram değildir. Aslında bunu kafanızda takip etmek daha zor olabilir, ama gerçekte en zor kısım, özyinelemenin ne zaman “kırıldığını” ne zaman durması gerektiğini (benim görüşüme göre, elbette.) Bilmek. önce özyineleme. Yalnızca kusurlu bir benzetmedir ve her özyinelemeli yinelemenin bir "geçiş" olduğunu varsayar. Yine, sadece bir görüş.

Uygulamada, okulun görülmesi daha zordur. Sayısal ve bankacılık defterleri "kolay" anlamında basit aritmetik kullanabilirsiniz. Bir + b görebilir ve 0, vb. Geri dönebilirim. Bir insan sistemi durumunda, bunun nasıl uygulanacağı konusunda daha fazla düşünmek zorundayım . Başarısızlık, başarılılık, refaktör kavramına sahibim (çoğunlukla çalışma ve bu soru yüzünden).

Bilmediklerim bana göre deneyim eksikliğine dayanıyor. Yeni bir öğrenciye kaydolma konusunda nasıl başarısız olacağımı bilmiyorum. Bir soyadını yazarak birinin başarısız ve nasıl bir veritabanına kaydedildiğini bilmiyorum. Basit bir matematik için nasıl + 1 yapılacağını biliyorum, ancak bir kişi gibi varlıklar ile, birileri bir isim girdiğinde yalnızca bir veritabanına benzersiz bir kimlik veya başka bir şey girip girmediğimi görmek için test yapıp yapmadığımı bilmiyorum. veritabanı veya her ikisi veya ikisi.

Ya da, belki de bu hala kafamın karıştığını gösteriyor.


193
TDD'den sonra insanlar gece eve gidiyor.
hobbs

14
Neden yazdığın kodun gerçek olmadığını düşünüyorsun?
Goyo

2
@RubberDuck Diğer cevaplardan daha fazla. Eminim yakında bahsedeceğim. Hala biraz yabancı, ama ondan vazgeçmeyeceğim. Söylediklerin anlam kazandı. Ben sadece bağlamımda veya düzenli bir iş başvurusunda anlam ifade etmeye çalışıyorum. Belki bir envanter sistemi veya benzeri. Bunu düşünmeliyim. Yine de zamanın için müteşekkirim. Teşekkürler.
johnny

1
Cevaplar zaten kafanın üstüne çiviyi vurdu, ancak tüm testleriniz geçtiği sürece ve herhangi bir yeni teste / işlevselliğe ihtiyaç duymadığınız sürece, sahip olduğunuz kodun bittiği, bar astarının olduğu varsayılabilir.
ESR

3
Soruda “karmaşık bir yöntemle oldukça karmaşık bir nesneye sahibim” de sorunlu olabilecek bir varsayım var. TDD'de önce testlerinizi yazıyorsunuz, böylece oldukça basit bir kodla başlıyorsunuz. Bu sizi modüler olması gereken test dostu bir yapıya kodlamanız için zorlar. Böylece daha basit nesneler birleştirilerek karmaşık davranışlar ortaya çıkar. Oldukça karmaşık bir nesneyle veya yöntemle sona
ererseniz

Yanıtlar:


243

Eğer karmaşık bir metotla oldukça karmaşık bir nesneye sahipsem ve testimi ve minimum seviyesini geçmesi için çıplak olarak yazarım (ilk başarısız olduktan sonra, Kırmızı). Ne zaman geri dönüp gerçek kodu yazacağım? Ve tekrar test etmeden önce ne kadar gerçek kod yazarım? Sanırım sonuncunun daha sezgi olduğunu düşünüyorum.

"Geri dön" ve "gerçek kod" yazmazsın. Hepsi gerçek kod. Ne yapmak geri dönüp başka bir test ekleyin zorlar size değiştirmek yeni test geçiş yapmak için kodunuzu.

Tekrar test etmeden önce ne kadar kod yazıyorsunuz? Yok. Daha fazla kod yazmaya zorlayan bir başarısızlık testi olmadan sıfır kod yazarsınız.

Desene dikkat edin?

Yardımcı olacağı umuduyla basit bir örnek üzerinden geçelim.

Assert.Equal("1", FizzBuzz(1));

Sakin ol

public String FizzBuzz(int n) {
    return 1.ToString();
}

Gerçek kod dediğiniz şey değil, değil mi? Değişikliği zorlayan bir test ekleyelim.

Assert.Equal("2", FizzBuzz(2));

Aptalca bir şey yapabiliriz if n == 1, ama mantıklı bir çözüme geçeceğiz.

public String FizzBuzz(int n) {
    return n.ToString();
}

Güzel. Bu, FizzBuzz dışındaki tüm numaralar için işe yarar. Üretim kodunu değişmeye zorlayacak bir sonraki girdi nedir?

Assert.Equal("Fizz", FizzBuzz(3));

public String FizzBuzz(int n) {
    if (n == 3)
        return "Fizz";
    return n.ToString();
}

Ve yeniden. Henüz geçmeyen bir test yazın.

Assert.Equal("Fizz", FizzBuzz(6));

public String FizzBuzz(int n) {
    if (n % 3 == 0)
        return "Fizz";
    return n.ToString();
}

Ve şimdi üçün tüm katlarını ele aldık (aynı zamanda beşin katları değil, bunu not edeceğiz ve geri döneceğiz).

Henüz "Buzz" için bir test yazmadık, o yüzden yazalım.

Assert.Equal("Buzz", FizzBuzz(5));

public String FizzBuzz(int n) {
    if (n % 3 == 0)
        return "Fizz";
    if (n == 5)
        return "Buzz"
    return n.ToString();
}

Ve yine, ele almamız gereken başka bir vaka olduğunu biliyoruz.

Assert.Equal("Buzz", FizzBuzz(10));

public String FizzBuzz(int n) {
    if (n % 3 == 0)
        return "Fizz";
    if (n % 5 == 0)
        return "Buzz"
    return n.ToString();
}

Ve şimdi 5'in katları değil, aynı zamanda 3'ün katları da olabiliriz.

Bu noktaya kadar, yeniden ateşleme adımını görmezden geldik, ancak bazı kopyalar görüyorum. Şimdi onu temizleyelim.

private bool isDivisibleBy(int divisor, int input) {
    return (input % divisor == 0);
}

public String FizzBuzz(int n) {
    if (isDivisibleBy(3, n))
        return "Fizz";
    if (isDivisibleBy(5, n))
        return "Buzz"
    return n.ToString();
}

Güzel. Şimdi kopyalamayı kaldırdık ve iyi adlandırılmış bir işlev oluşturduk. Kodu değiştirmeye zorlayacak bir sonraki test ne olabilir? Numaranın hem 3 hem de 5 tarafından bölünebilir olduğu durumdan kaçınıyoruz. Şimdi yazalım.

Assert.Equal("FizzBuzz", FizzBuzz(15));

public String FizzBuzz(int n) {
    if (isDivisibleBy(3, n) && isDivisibleBy(5, n))
        return "FizzBuzz";
    if (isDivisibleBy(3, n))
        return "Fizz";
    if (isDivisibleBy(5, n))
        return "Buzz"
    return n.ToString();
}

Testler başarılı, ama daha fazla çoğaltmamız var. Seçeneklerimiz var, ancak "Yerel Değişkenleri Çıkar" ı birkaç kez uygulayacağım, böylece yeniden yazmak yerine yeniden yönlendiriyoruz.

public String FizzBuzz(int n) {

    var isDivisibleBy3 = isDivisibleBy(3, n);
    var isDivisibleBy5 = isDivisibleBy(5, n);

    if ( isDivisibleBy3 && isDivisibleBy5 )
        return "FizzBuzz";
    if ( isDivisibleBy3 )
        return "Fizz";
    if ( isDivisibleBy5 )
        return "Buzz"
    return n.ToString();
}

Ve makul olan her girdiyi ele aldık, ama ya mantıksız girdi? 0 ya da negatif olarak geçersek ne olur? Bu test durumlarını yazın.

public String FizzBuzz(int n) {

    if (n < 1)
        throw new InvalidArgException("n must be >= 1);

    var isDivisibleBy3 = isDivisibleBy(3, n);
    var isDivisibleBy5 = isDivisibleBy(5, n);

    if ( isDivisibleBy3 && isDivisibleBy5 )
        return "FizzBuzz";
    if ( isDivisibleBy3 )
        return "Fizz";
    if ( isDivisibleBy5 )
        return "Buzz"
    return n.ToString();
}

Bu henüz "gerçek kod" gibi görünmeye başladı mı? Daha önemlisi, hangi noktada “gerçek dışı kod” olmaktan ve “gerçek” olmaktan vazgeçti? Bu üzerinde durulması gereken bir şey ...

Böylece, bunu her adımda geçmeyeceğimi bildiğim bir test arayarak yapabildim, ama çok fazla pratik yaptım. İşteyken, işler hiç bu kadar basit değildir ve hangi testin bir değişikliği zorlayacağını her zaman bilemeyebilirim. Bazen bir test yazacağım ve geçtiğini görmek beni şaşırttı! Başlamadan önce bir "Test Listesi" oluşturma alışkanlığına sahip olmanızı şiddetle tavsiye ederim. Bu test listesi aklınıza gelebilecek tüm "ilginç" girişleri içermelidir. Hepsini kullanmayabilir ve gittiğinizde büyük olasılıkla davalar eklersiniz, ancak bu liste yol haritası görevi görür. FizzBuzz için test listem buna benzer bir şey olabilir.

  • Olumsuz
  • Sıfır
  • Bir
  • İki
  • Üç
  • dört
  • Beş
  • Altı (önemsiz 3 katı)
  • Dokuz (3 kare)
  • On (önemsiz 5 katı)
  • 15 (3 ve 5 katı)
  • 30 (önemsiz 3 ve 5 katları)

3
Yorumlar uzun tartışmalar için değildir; bu konuşma sohbete taşındı .
maple_shaft

47
Bu cevabı tamamen yanlış anlamadığım sürece: "n == 1 ise aptalca bir şey yapabiliriz, ancak mantıklı bir çözüme geçeceğiz." - her şey aptaldı. Önceden biliyorsanız, <spec> işlevini kullanmak istiyorsanız, <spec> testlerini yazın ve açıkça <spec> başarısız olan sürümleri yazdığınız kısmı atlayın. <spec> 'de bir hata bulursanız emin olun: düzeltmeden önce egzersiz yapabileceğinizi doğrulamak için önce bir test yazın ve düzeltmeden sonra test geçişlerini gözlemleyin. Ancak bütün bu ara adımları atmaya gerek yok.
GManNickG

16
Bu cevaptaki ve genel olarak TDD'deki ana eksiklikleri belirten yorumlar sohbete taşındı. TDD'yi kullanmayı düşünüyorsanız, lütfen 'sohbeti' okuyun. Maalesef, 'kaliteli' yorumlar şimdi gelecekteki öğrencilerin okuması gereken bir sohbet yükü arasında gizlenmiştir.
user3791372

2
@GManNickG Amacım doğru miktarda test almak olduğuna inanıyorum. Testleri önceden yazmak, hangi özel durumların test edileceğini kaçırmayı kolaylaştırır, bu da testlerde yeterince kapsanamayan durumlara veya temelde testlerde çok kez kapsanan aynı durumun ortaya çıkmasına neden olur. Bu ara adımlar olmadan bunu yapabilirseniz, harika! Yine de herkes bunu yapamaz, ancak pratik gerektiren bir şey.
hvd

1
Ve işte Kent Beck'ten yeniden yapılanma üzerine bir alıntı: "Artık test çalıştığında, (" gerçek yap "gibi) özetin () uygulandığını anlayabiliriz . Daha sonra bir değişkeni sabit olarak değiştirmeye devam eder. Bu teklifin soruyu oldukça iyi eşleştirdiğini hissettim.
Chris Wohlert

46

"Gerçek" kod, testinizi geçmek için yazdığınız koddur. Gerçekten . Bu kadar basit.

İnsanlar testi yeşil yapmak için çıplaklığı yazmaktan bahsettiklerinde, bu sadece gerçek kodunuzun YAGNI ilkesini izlemesi gerektiği anlamına gelir .

Refactor adımının fikri, sadece gereklilikleri karşıladığı için mutlu olduğunuzda yazdıklarınızı temizlemektir.

Yazdığınız testler aslında ürün gereksinimlerinizi kapsadığı sürece, geçtikten sonra kod tamamlanır. Bir düşünün, tüm iş gereksinimlerinizin bir testi varsa ve bu testlerin tümü yeşilse, daha ne yazacak? (Tamam, gerçek hayatta tam bir test kapsamına girme eğiliminde değiliz, ancak teori sağlam.)


45
Birim testleri aslında nispeten önemsiz gereksinimler için bile ürün gereksinimlerinizi kapsayamaz. En iyi durumda, girdi-çıktı alanını örnekliyorlar ve fikir (doğru) tam girdi-çıktı alanını genelleştiriyor olmanız. Elbette, kodunuz switchtüm testleri geçecek ve diğer girişler için başarısız olacak her birim testi için bir durumla büyük olabilir .
Derek Elkins,

8
@DerekElkins TDD başarısız testlerini zorunlu kılar. Başarısız olmayan ünite testleri.
Taemyr

6
@DerekElkins bu yüzden sadece ünite testleri yazmıyorsunuz ve aynı zamanda sadece sahte bir şey yapmaya çalıştığınıza dair genel bir varsayım var!
jonrsharpe

36
@ jonrsharpe Bu mantıkla, asla önemsiz uygulamalar yazmam. Örneğin RubberDuck'ın cevabındaki (sadece birim testlerini kullanan) FizzBuzz örneğinde, ilk uygulama açıkça "sadece sahtedir". Soruyu anlamam, tam olarak bildiğiniz kodun eksik olduğunu ve gerçekten de "gerçek kod" şartını uygulayacağına inandığınız kod arasındaki bu ikiliktir. Benim "büyüküm switch", "testleri yeşil yapmak için en ufak bir çabayı yazmaya" mantıklı bir uçurum olarak düşünülmüştü. OP’nin sorusunu şu şekilde görüyorum: TDD’de bu kadar büyük olan ilkenin neresi switch?
Derek Elkins

2
@GenericJon Bu benim deneyimim biraz fazla iyimser :) Birincisi, akılsız tekrarlayan çalışma zevk insanlar var. Devasa bir anahtar ifadesiyle "karmaşık bir karar vermekten" daha mutlu olacaklar. Ve işlerini kaybetmek için, onları tekniğe çağıran birine ihtiyaçları var (ve şirket fırsatlarını / parasını kaybettiğine dair iyi kanıtları olsa iyi olur!) Veya istisnai olarak kötü. Bu tür birçok projenin bakımını üstlendikten sonra, çok saf kodun, müşteriyi mutlu ettiği (ve ödeme yaptığı) yıllar boyunca sürmesi kolay olduğunu söyleyebilirim.
Luaan

14

Kısa cevap, “gerçek kodun” testi geçmesini sağlayan kod olmasıdır. Testinizin gerçek kod dışında bir şeyle geçmesini sağlayabiliyorsanız, daha fazla test ekleyin!

TDD ile ilgili birçok öğreticinin basit olduğuna katılıyorum. Bu onlara karşı çalışır. 3 + 8 hesaplayan bir yöntem için çok basit bir testin, 3 + 8'i hesaplamak ve sonucu karşılaştırmaktan başka çaresi yok. Bu, sadece kodun her yerini kopyalayacağınız gibi görünmesini sağlar ve testin anlamsız, hataya açık ilave bir çalışma olduğunu gösterir.

Testte başarılı olduğunuzda, bu, uygulamanızı nasıl yapılandırdığınızı ve kodunuzu nasıl yazdığınızı gösterir. Mantıklı ve yararlı testler yapmakta zorlanıyorsanız, tasarımınızı biraz düşünmelisiniz. İyi tasarlanmış bir sistemin test edilmesi kolaydır - mantıklı testlerin düşünülmesi ve uygulanması kolaydır.

Önce testlerinizi yazdığınızda, başarısız olduklarını ve ardından geçmelerini sağlayan kodu yazın; bu, tüm kodunuzun ilgili testlere sahip olmasını sağlamak için bir disiplindir. Kod yazarken bu kuralı acımasızca takip etmiyorum; sık sık testlerden sonra testleri yazarım. Fakat önce testleri yapmak sizi dürüst tutmanıza yardımcı olur. Bazı deneyimlerle, önce testler yazmıyor olsanız bile, kendinizi bir köşeye kodladığınızda fark etmeye başlayacaksınız.


6
Şahsen, yazacağım test assertEqual(plus(3,8), 11)değil assertEqual(plus(3,8), my_test_implementation_of_addition(3,8)). Daha karmaşık durumlar için , testte doğru sonucu dinamik olarak hesaplamak ve eşitliği kontrol etmek dışında , sonucu doğru kanıtlamanın bir yolunu ararsınız.
Steve Jessop

Yani bu örnek için bunu yapmanın gerçekten saçma bir yol, bunu ispat olabilir plus(3,8), ondan 3 çıkararak bundan 8 çıkararak ve bu yüzden açıkçası eşdeğerdir 0. karşı sonucunu kontrol ederek doğru sonucu döndürdü assertEqual(plus(3,8), 3+8)bir olmak üzere bit saçma, ama eğer test edilen kod sadece bir tamsayıdan daha karmaşık bir şey inşa ediyorsa, sonucu almak ve doğruluk için her parçayı kontrol etmek çoğu zaman doğru bir yaklaşımdır. Alternatif olarak, gibi bir şeyfor (i=0, j=10; i < 10; ++i, ++j) assertEqual(plus(i, 10), j)
Steve Jessop

... bu büyük korkuyu önlediğinden, testi yazarken canlı kodda yaptığımız "nasıl 10 eklenir?" konusunda aynı hatayı yapacağız. Bu nedenle test, testlere her şeye plus()10 ekleyebilecek herhangi bir kod yazmaktan kaçınır . Tabii ki hala programcının doğruladığı intial loop değerlerine güveniyoruz.
Steve Jessop

4
Sadece, gerçekte testler yazsanız bile, başarısızlıklarını izlemek için hala iyi bir fikir olduğunu belirtmek isterim; Çalıştığınız şey için çok önemli görünen kodun bir bölümünü bulun, biraz ayarlayın (örneğin a + ile - veya ne olursa olsun), testleri yapın ve başarısız olduklarını izleyin, değişikliği geri alın ve geçmelerini izleyin. Bunu birçok kez yaptım, test aslında başarısız değil, işe yaramazdan daha kötü hale geldi: sadece bir şeyi test etmekle kalmıyor, aynı zamanda bir şeyin test edildiğine dair yanlış bir güven veriyor!
Warbo,

6

Bazen TDD ile ilgili bazı örnekler yanıltıcı olabilir. Diğer kişilerin daha önce de belirttiği gibi, testleri geçmek için yazdığınız kod gerçek koddur.

Fakat gerçek kodun sihir gibi göründüğünü düşünmeyin - bu yanlış. Neyi başarmak istediğinizi daha iyi anlamanız gerekir ve ardından en kolay ve köşe kasalardan başlayarak testi uygun şekilde seçmeniz gerekir.

Mesela, bir lexer yazmanız gerekiyorsa, boş bir dize, sonra bir sürü beyaz boşlukla, sonra bir rakamla, sonra beyaz boşluklarla çevrili bir rakamla, sonra yanlış bir rakamla vb. Başlarsınız. Bu küçük dönüşümler sizi yönlendirecektir. Doğru algoritma, ancak en kolay durumdan, gerçek kodu elde etmek için aptalca seçilen oldukça karmaşık bir duruma geçemezsiniz.

Bob Martin burada mükemmel anlatıyor .


5

Refactor kısmı yorgun olduğunuzda ve eve gitmek istediğinizde temizlenir.

Bir özellik eklemek üzereyken, refactor kısmı bir sonraki testten önce değiştirdiğiniz kısımdır. Yeni özelliğe yer açmak için kodu yeniden adlandırıyorsunuz. Bunu , yeni özelliğin ne olacağını bildiğiniz zaman yaparsınız . Sadece hayal ederken değil.

Bu adlandırma kadar basit olabilir GreetImpliçin GreetWorldbir oluşturmadan önce GreetMom"Merhaba Anne" yazdırır bir özellik eklemek (bir test ekledikten sonra) sınıfı.


1

Ancak gerçek kod TDD fazının refactor aşamasında görünecektir. Yani son sürümün bir parçası olması gereken kod.

Her değişiklik yaptığınızda testler yapılmalıdır.

TDD yaşam döngüsünün sloganı şöyle olurdu: KIRMIZI YEŞİL REFAKTÖR

KIRMIZI : Testleri yaz

YEŞİL : Testleri olabildiğince çabuk geçen işlevsel bir kod almak için dürüst bir girişimde bulunun: yinelenen kod, belirsiz olarak adlandırılmış değişkenleri en yüksek dereceden kesen kodlar vb.

REFACTOR : Kodu temizleyin , değişkenleri uygun şekilde adlandırın. KURUTMA kodu.


6
"Yeşil" aşaması hakkında ne söylediğinizi biliyorum, ancak testleri geçmek için zor kablolama dönüş değerlerinin uygun olabileceği anlamına gelir. Tecrübelerime göre "Yeşil" gereksinimi karşılamak için çalışma kodunu yapmak için dürüst bir girişim olmalı, mükemmel olmayabilir ancak geliştiricinin ilk aşamada yönetebildiği kadar eksiksiz ve "elverişli" olmalıdır. Yeniden yapılanma, daha fazla gelişme gösterdikten bir süre sonra muhtemelen en iyi şekilde yapılır ve ilk geçişle ilgili sorunlar daha belirgin hale gelir ve DRY için fırsatlar ortaya çıkar.
mcottle

2
@mcottle: bir salt okunur havuzun ne kadar uygulamasının kod tabanında kodlanmış değerler olduğuna şaşırabilirsiniz. :)
Bryan Boettcher

6
Niçin yazabildiğim kadar hızlı bir şekilde, üretim kodunu güzel bir şekilde çıkarabildiğimde neden kod yazıp temizleyeyim? :)
Kaz

1
@Kaz Çünkü bu şekilde denenmemiş davranış ekleme riski . İstenen her davranış için test yaptırmayı sağlamanın tek yolu, ne kadar berbat olursa olsun basit olan değişiklikleri yapmaktır . Bazen aşağıdaki yeniden düzenleme, önceden düşünemediğiniz yeni bir yaklaşım ortaya
koyuyor

1
@TimothyTruckle Mümkün olan en basit değişikliği bulmak için 50 dakika, ikinci olası en basit değişikliği bulmak için sadece 5 dakika geçerse ne olur? En basit ikinci olanla mı gidiyoruz yoksa en basit olanı aramaya mı devam ediyoruz?
Kaz,

1

TDD'ye “gerçek” kodu ne zaman yazıyorsunuz?

Kırmızı nerede aşamasıdır yazma kodu.

Gelen yeniden düzenleme faza birincil hedef olduğunu silme kodu.

In kırmızı faz test geçmesi için her şeyi mümkün olduğunca çabuk ve ne pahasına olursa olsun . İyi kodlama uygulamalarından ya da tasarım modelinden duyduğunuzu tamamen aynı şekilde dikkate almazsınız. Testi yeşil yapmak önemli.

Gelen üstlenmeden fazı size sadece yapılan pisliği temizlemeye. Şimdi ilk önce yaptığınız değişikliğin Dönüşüm Önceliği listesindeki en üst tür olup olmadığına bakarsınız ve herhangi bir kod çoğaltması varsa, büyük olasılıkla bir tasarım bildiri uygulayarak kaldırabilirsiniz.

Sonunda, tanımlayıcıları yeniden adlandırarak okunabilirliği arttırır ve sihirli sayıları ve / veya değişmez karakter dizilerini sabitlere çıkarırsınız.


Kırmızı-refactor değil, kırmızı-yeşil-refactor. - Rob Kinyon

Buna işaret ettiğin için teşekkürler.

Demek gerçek kodu yazdığın yeşil evre.

In kırmızı faz yazdığınız yürütülebilir şartname ...


Kırmızı-refactor değil, kırmızı-yeşil-refactor. "Kırmızı", test takımınızı yeşilden (tüm testlerden başarılı) kırmızıya (bir test başarısız) geçiyor. "Yeşil", test takımınızı kırmızıdan (bir testin başarısız olması) yeşile (tüm testlerin geçmesi) dikkatlice götürdüğünüz yerdir. "Refactor", tüm testleri geçerken kodunuzu aldığınız ve güzel yaptığınız yerdir.
Rob Kinyon

1

Her zaman Gerçek Kod yazıyorsun .

Her adımda, kodunuzun gelecekteki arayanları için kodunuzun yerine getireceği koşulları sağlayacak kod yazıyorsunuz (ki siz ya da olmayabilirsin ...).

Faydalı ( gerçek ) kod yazmadığınızı düşünüyorsunuz , çünkü bir dakika içinde yeniden düzeltebilirsiniz.

Kod Yenileme , dış davranışını değiştirmeden mevcut bilgisayar kodunu (faktoringi değiştirerek) yeniden yapılandırma işlemidir.

Bunun anlamı, kodu değiştirseniz bile, kodun sağladığı koşullar değişmeden kalır. Ve kodunuzu doğrulamak için uyguladığınız kontroller ( testler ) Yaptığınız değişikliklerin bir şeyleri değiştirip değiştirmediğini doğrulamak için zaten oradasınız. Demek bütün zaman boyunca yazdığın kod orada, farklı bir şekilde.

Bunun gerçek bir kod olmadığını düşünebilmenizin bir başka nedeni de, nihai programın zaten sizin tarafınızdan öngörülebileceği örnekleri yapıyor olmanızdır. Bu da hakkında bilgi sahibi gösterdiği gibi, çok iyi etki İçeri programlama.
Fakat birçok kez programcılar bir içindedir etki olduğunu yeni , bilinmeyen onlara. Nihai sonucun ne olacağını bilmiyorlar ve TDD, bu sistemin nasıl çalışması gerektiğiyle ilgili bilgimizi belgeleyen ve kodumuzun bu şekilde çalıştığını doğrulayan programları adım adım yazma tekniğidir .

TDD'deki Kitabı (*) okuduğumda, benim için öne çıkan en önemli özellik: TODO listesiydi. TDD'nin, geliştiricilerin aynı anda bir şeye odaklanmalarına yardımcı olacak bir teknik olduğunu gösterdi. Öyleyse bu aynı zamanda soruna cevaben ne kadar Gerçek kod yazmalı ? Her seferinde 1 şeye odaklanmak için yeterli kod söyleyebilirim.

(*) Kent Beck tarafından "Test Odaklı Gelişme: Örnek Olarak"


2
"Test Driven Development: Örnek olarak" Kent Beck
Robert Andrzejuk

1

Testlerinin başarısız olması için kod yazmıyorsun.

Testlerinizi, başarının nasıl görünmesi gerektiğini tanımlamak için yazıyorsunuz, ki bunlar başlangıçta başarısız olmalı, çünkü geçecek kodu henüz yazmadınız.

Başlangıçta başarısızlık sınamaları yazmakla ilgili bütün mesele iki şey yapmaktır:

  1. Tüm kılıfları örtün - tüm nominal kılıfları, tüm kenar kılıfları vb.
  2. Testlerini doğrula. Onları sadece geçtikten sonra görürseniz, bir hata meydana geldiğinde bir hatayı güvenilir bir şekilde rapor edeceklerinden nasıl emin olabilirsiniz?

Red-green-refactor'ın arkasındaki nokta, doğru testlerin yazılmasının, testleri geçmek için yazdığınız kodun doğru olduğunu bildiğinize dair güven vermesi ve en kısa sürede testlerinizin sizi bilgilendireceği konusunda kendinize güven vermenizdir. Bir şeyler kırılır, hemen geri dönüp düzeltebilirsiniz.

Kendi deneyimlerime göre (C # /. NET), ilk önce saf deneme, erişilemez bir idealdir, çünkü henüz mevcut olmayan bir metoda yapılan çağrıyı derleyemezsiniz. Bu yüzden, "ilk önce test" gerçekten arayüzleri kodlamak ve ilk önce taslak uygulamaları yapmak, sonra da taslakları doğru bir şekilde parçalayana kadar taslaklara (başlangıçta başarısız olacak) karşı testler yazmakla ilgilidir. Asla "başarısız kod" yazmıyorum, sadece taslaklardan yapıyorum.


0

Birim testleri ile entegrasyon testleri arasında kafa karışıklığına neden olabileceğinizi düşünüyorum. Kabul testleri de olabileceğine inanıyorum, ancak bu işleminize bağlı.

Tüm küçük birimleri "bir kez" test ettikten sonra hepsini birleştirilmiş veya "entegre" olarak test edersiniz. Bu genellikle bütün bir program veya kütüphanedir.

Bütünleştirmeyi yazdığım kodda, verileri okuyan ve onu kütüphaneye besleyen çeşitli test programları içeren bir kitaplık test edilir, ardından sonuçları kontrol edin. Sonra konuları ile yapıyorum. Sonra ortadaki dişler ve çatal () ile yapıyorum. Sonra koşup 2 saniye sonra -9'u öldürdüm, sonra başlatıp kurtarma modunu kontrol ediyorum. Kafayı karıştırdım. Her türlü şekilde işkence ediyorum.

Bunların hepsi ALSO testi, ancak sonuçlar için oldukça kırmızı / yeşil bir ekranım yok. Ya başarılı olabilir, ya da nedenini bulmak için birkaç bin satırlık hata kodunu kazıyorum.

Gerçek kodu test ettiğiniz yer burasıdır.

Ben de bunu düşündüm, ama belki de ne zaman ünite testleri yazman gerektiğini bilmiyorsun. Testleriniz, yapması gereken her şeyi yaptığınızda, birim testleri yazmanız gerekir. Bazen tüm hata yönetimi ve kenar durumları arasında bunun izini kaybedebilirsiniz, bu nedenle, doğrudan spesifikasyonların içinden geçen iyi bir test yolu mutlu yol testi yapmak isteyebilirsiniz.


(= iyelik, = "olduğu" veya "olduğu". Örneğin , Kullanımı ve Kullanılması konusuna bakın .)
Peter Mortensen

-6

Sorunun başlığına cevaben: "TDD'ye" gerçek "kodu ne zaman yazıyorsunuz?", Cevap: 'hemen hemen hiç' veya 'çok yavaş'.

Bir öğrenci gibi konuşuyorsunuz, ben de bir öğrenciyi tavsiye ediyormuş gibi cevaplayacağım.

Pek çok kodlama “teorisi” ve “teknik” öğreneceksiniz. Zamanını overpriced öğrenci kurslarında geçirmek için harikalar, ancak yarı zamanlı olarak bir kitapta okuyamadığınız için size çok az yararı var.

Bir kodlayıcının işi yalnızca kod üretmektir. Gerçekten iyi çalışan kod. Bu nedenle, kodlayıcı aklınızdaki, kağıda, uygun bir uygulamadaki vb. Kodları planlar ve kodlamadan önce mantıklı ve yanal düşünerek olası kusurlar / delikler etrafında çalışmayı planlıyorsunuz.

Ancak düzgün bir kod tasarlayabilmek için başvurunuzu nasıl kıracağınızı bilmeniz gerekir. Örneğin, Küçük Bobby Tablosu (xkcd 327) hakkında bir şey bilmiyorsanız , o zaman muhtemelen veritabanınızla çalışmadan önce girdilerinizi dezenfekte edemezsiniz, bu nedenle verilerinizi bu kavram etrafında koruyamazsınız.

TDD, uygulamanızı kodlamadan önce neyin yanlış gidebileceğinin testlerini oluşturarak kodunuzdaki hataları en aza indirmek için tasarlanmış bir iş akışıdır; Başvurunuzu tamamladığınızı düşündüğünüzde, testleri uygular ve patlarsınız, umarım hatalarınız testlerinizle sonuçlanır.

TDD değildir - bazılarının inandığı gibi - bir test yazın, minimum kodla geçmesini sağlayın, başka bir test yazın, minimum kodla geçmenizi sağlayın, vb. Bunun yerine, güvenle kod yazmanıza yardımcı olur. Testlerle çalışmasını sağlamak için sürekli yeniden kodlama kodunun bu ideali aptalca, ancak öğrenciler arasında hoş bir kavram çünkü yeni bir özellik eklediklerinde kendilerini harika hissettiriyorlar ve hala kodlamayı öğreniyorlar ...

Lütfen bu tuzağı düşürmeyin ve ne olduğuna ilişkin kodlama rolünüzü görün - bir kodlayıcının işi yalnızca kod üretmektir. Gerçekten iyi çalışan kod. Şimdi, profesyonel bir kodlayıcı olarak saatte olacağınızı ve 100.000 iddia veya 0 yazdığınızda müşteriniz umursamayacağınızı unutmayın. Aslında çok iyi.


3
Öğrenciye bile yakın değilim, ancak iyi teknikleri uygulayıp profesyonel olmaya çalışıyorum. Yani bu anlamda ben bir "öğrenciyim". Sadece çok basit sorular soruyorum çünkü bu benim olduğum gibi. Yaptığım şeyi neden yaptığımı tam olarak bilmek hoşuma gidiyor. Maddenin kalbi. Bunu anlamıyorsam, hoşuma gitmiyor ve sorular sormaya başladım. Eğer kullanacaksam nedenini bilmem gerekiyor. TDD, neyi yaratmanız gerektiğini bilmek ve bazı şeyleri düşünmek gibi sezgisel olarak iyi görünüyor, ancak uygulamanın anlaşılması zordu. Sanırım şimdi daha iyi bir fikrim var.
johnny


4
Bunlar TDD'nin kuralları. İstediğiniz gibi kod yazmakta özgürsünüz, ancak bu üç kurala uymazsanız TDD yapmıyorsunuzdur.
Sean Burton,

2
Bir kişinin "Kuralları"? TDD size bir dinin değil kod yazmanız için bir öneridir. Bu kadar çok insanın bir analize bu kadar bağlı olduğunu görmek üzücü. TDD'nin kökeni bile tartışmalıdır.
user3791372

2
@ user3791372 TDD çok katı ve açıkça tanımlanmış bir işlemdir. Birçoğu bunun sadece "Programlama yaparken bazı testler yapın" anlamına geldiğini düşünüyor olsa bile, değildir. Burada terimleri karıştırmamaya çalışalım, bu soru genel test değil, TDD süreci ile ilgili.
Alex,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.