TDD'de bebek basamaklarınız nasıl?


37

Bugün TDD'yi eğitiyorduk ve aşağıdaki yanlış anlama noktasını bulduk.

Görev, "1,2" girişi için, 3 olan sayıların toplamıdır. Yazdıklarım (C #):

numbers = input.Split(',');
return int.Parse(numbers[0]) + int.Parse(numbers[1]); //task said we have two numbers and input is correct

Fakat diğer çocuklar bunu başka şekilde yapmayı tercih etti. İlk önce "1,2" girişi için aşağıdaki kodu eklediler:

if (input == "1,2")
   return 3;

Ardından "4,5" girişi için bir test daha yaptılar ve uygulama değişti:

if (input == "1,2")
   return 3;
else if (input == "4,5")
   return 9;

Ve ondan sonra "Tamam, şimdi deseni görüyoruz" dediler ve başlangıçta yaptığım şeyi uyguladılar.

İkinci yaklaşımın TDD tanımına daha uygun olduğunu düşünüyorum ama ... bu konuda çok mu katı olmalıyız? Benim için önemsiz bebek adımlarını atlamak ve hiçbir şeyi atlamamaya yetecek kadar emrim varsa bunları "ikiz adımlarla" birleştirmek tamamdır. Yanlış mıyım?

Güncelleme. İlk test olmadığını açıklığa kavuşturarak bir hata yaptım. Zaten bazı testler yapıldı, bu nedenle "return 3" gereksinimi karşılayacak en basit kod parçası değildi.


25
İş arkadaşlarım "Ooahhh dazso cuuuuuute" fışkırtığında çok küçük
Adel,

6
@Adel: Neredeyse kahvaltı yuttum, klavye artık tam veya tükürük ve kırıntıları
İkili worrier

2
@Adel, anadili olmayan konuşmacılar için olduğu gibi, bu mizahı anlamak benim için oldukça zor, ancak iş arkadaşlarınız soruyu beğeniyorum :)
SiberianGuy

8
@ Idsa: Bir çocuğun ilk adımları "Ooahhh dazso cuuuuuute" = "Ah, çok tatlı bir sesle konuşulan", "çok tatlı bir sesle konuşulan" şeklinde gösterilen bir iş arkadaşının cevabını aktarıyor. Adel tarafından yazılan Unit Testleri görünce, Unit Tests'e bakarken bebek adımlarına “Oh çok tatlı” diyorlar. Gerçek bebeklere verilen tepkiler = birim testlerine verilen tepki "bebek adımları".
İkili Kurtuluş

3
@Binaryworrier diliyorum, anne babalık açıklamaya zaman ayırdığınız için size gerçek puanlar verebilirim
Andrew T Finnell 22:11

Yanıtlar:


31

Testlerin başarılı olmasını sağlayan en basit kodu yazın.

Hiçbiriniz, görebildiğim kadarıyla yapmadınız.

Bebeğim Adım 1.

Test: "1,2" girişi için 3 olan sayıların toplamı

Testin başarısız olmasını sağlayın:

throw NotImplementedException();

Testin geçmesini sağlayın:

return 3;

Bebeğim Adım 2.

Test: "1,2" girişi için 3 olan sayıların toplamı

Test: "4,5" girişi için 9 olan sayıların toplamı

İkinci test başarısız olur, bu yüzden geçmesini sağlayın:

numbers = input.Split(',');
return int.Parse(numbers[0]) + int.Parse(numbers[1]);

(Eğer bir listeden çok daha basit ... dönüş)

Bu durumda Açıkça Uygulama'yı kesinlikle tartışabilirsiniz, ancak bunu kesinlikle bebek adımlarında yapmaktan söz ediyorsanız, bunlar doğru adımlardır, IMO.

Argüman, eğer ikinci testi yazmazsanız, bazı parlak kıvılcımlar daha sonra ortaya çıkabilir ve kodunuzu "refactor" olarak okuyabilirsiniz:

return input.Length; # Still satisfies the first test

Ve, her iki adımı atmadan, hiçbir zaman ikinci testi kırmızılaştırmadınız (testin kendisinin şüpheli olduğu anlamına gelir).


Girdilerinize ilişkin. Uzunluk örneği, aynı başarıda, her iki testte de yakalanmayacak bazı yanlış uygulamaların olduğunu hayal edebiliyorum
SiberianGuy

@ Idsa - Evet, kesinlikle ve ne kadar çok test yazarsanız, uygulama da o kadar çılgınca olur. input.Lengtho kadar da zor değil, özellikle yöntemin girişi bir yerdeki bir dosyadan bir ölçümse ve siz istemeyerek yönteminizi çağırdıysanız Size().
pdr

6
+1. TDD'nin nasıl öğrenileceği ile ilgili olarak, doğru yol budur. Bunu öğrendikten sonra, bazen doğrudan doğrudan uygulamaya geçebilirsiniz, ancak TDD'ye dair bir fikir edinmek için bu çok daha iyidir.
Carl Manaster

1
"Test" in kendisiyle ilgili bir sorum var. "4,5" girişi için yeni bir test yazar mı yoksa orijinal testi değiştirir misiniz?
mxmissile

1
@mxmissile: Yeni bir test yazardım. Çok fazla zaman almaz ve daha sonra yeniden yapılanma yaparken sizi korumak için iki kat fazla test yaptırırsınız.
pdr,

50

Bence ikinci yol zihinsel olarak aptalca bir zihin. Yeterince küçük adımlar atmanın değerini anlıyorum, ancak bu küçük zigotu yazmak (onlara bebek bile diyemez) adımları sadece asinine ve zaman kaybı. Özellikle, çözdüğünüz asıl sorun zaten kendi başına çok küçükse.

Eğitim olduğunu ve ilkenin gösterilmesi hakkında daha fazla şey olduğunu biliyorum, ancak böyle örneklerin TDD'yi iyiden daha kötü yaptığını düşünüyorum. Bebek adımlarının değerini göstermek istiyorsanız, en azından içinde bir değerin olduğu bir problem kullanın.


+1 ve beni arama ve yeni bir kelime (asinine) öğrendiğim için teşekkürler
Marjan Venema

12
Uyuşuk salakça çağırmak için + 1 TDD'nin hepsi güzel ve böyle, ancak herhangi bir modern hiper programlama tekniğinde olduğu gibi, içine kaybolmamaya özen göstermelisiniz.
stijn

2
“Özellikle çözdüğünüz asıl sorun zaten kendi başına çok küçükse”. - Girdi birlikte eklenecek iki inç olsaydı, buna katılırdım, ancak "bir dize bölüştürün, sonuçtan iki inç ayırın ve ekleyin" olduğunda ikna olmadım. Gerçek dünyadaki çoğu yöntem bundan daha karmaşık değildir. Aslında, iki virgül, tamsayı olmayan değerler vb. Gibi kenar durumları kapsayacak daha fazla test yapılması gerekiyor.
pdr

4
Pdr: Kenar davaları ele almak için daha fazla test yapılması gerektiğine katılıyorum. Bunları yazdığınızda ve uygulamanızın onları idare etmek için değişmesi gerektiğine dikkat edin, elbette bunu yapın. Sanırım sadece bunu yazmak ve oradan devam etmek yerine ilk mutlu yoldaki “açık bir uygulamaya” zigot adımlarını atmakla ilgili bir sorunum var. Vücudumdaki her lifin bir sonraki anda kaybolacağını bildiği bir if ifadesini yazarken değeri göremiyorum.
Christophe Vanfleteren

1
@ChristopheVanfleteren: Beck bariz uygulanmasını açıklar, o bir örnek olarak iki ints toplamını kullanır ve hala size çifti / inceleme yapar daha basit kod düşünmek eğer utanç öleceğiz konusunda büyük bir dramatik uyarı atar Test geçişi. Bu senaryo için yalnızca bir test yazarsanız, bu kesin bir kesinliktir. Ayrıca, bu sorunu çözmek için en az üç "açık" yol düşünebilirim: böl ve ekle, virgül + ile değiştir ve değerlendir ya da regex kullanarak. TDD'nin amacı, sizi doğru seçime yönlendirmektir.
pdr

19

Kent Beck bunu, Test Driven Development: Örnek olarak adlı kitabında anlatıyor.

Örneğiniz ' belirgin bir uygulama ' olduğunu gösteriyor - toplam iki girdi değerini döndürmek istiyorsunuz ve bu elde edilmesi oldukça basit bir algoritma. Karşı örneğiniz, (bunu yapana kadar sahte yapın) içine düşüyor (çok basit bir durumda olmasına rağmen).

Bariz uygulama bundan çok daha karmaşık olabilir - ancak temel olarak bir yönteme ilişkin spesifikasyonun oldukça sıkı olduğu durumlarda devreye girer - örneğin, bir sınıf özelliğinin URL kodlu sürümünü döndürür - bir demet zaman harcamak zorunda değilsiniz sahte kodlamalar.

Diğer yandan, bir veri tabanı bağlantı yordamı biraz daha fazla düşünmeye ve test etmeye ihtiyaç duyar, bu nedenle açık bir uygulama yoktur (zaten birkaç kez başka projelere yazmış olsanız bile).

Kitaptan:

TDD'yi pratikte kullandığımda, bu iki uygulama modu arasında genel olarak geçiş yapıyorum, Her şey düzgün gidiyor ve ne yazacağımı biliyorum, Açık Uygulamanın ardından Açık Uygulamayı koydum (her seferinde testleri çalıştırarak bana açık olanı sağlamak için bilgisayara hala açık). Beklenmedik bir kırmızı çubuk alır almaz yedeklerim, taklit uygulamalara geçerim ve doğru koda göre yeniden düzenlerim. Güvenim geri döndüğünde, Belli Uygulamalara geri dönüyorum.


18

Bunu hukukun mektubunu takip ederken görüyorum, ama onun ruhunu değil.

Bebeğinizin adımları şöyle olmalı:

Mümkün olduğunca basit, ama daha basit değil.

Ayrıca, yöntemdeki fiil sum

if (input == "1,2")
   return 3;

toplam değil, belirli girdiler için bir testtir.


4

Bana göre birkaç önemsiz uygulama adımını biraz daha önemsiz bir hale getirmek iyi görünüyor - Ben de bunu her zaman yapıyorum. Birinin TDD'yi her zaman mektuba uyması konusunda dinlenmeye ihtiyacı olduğunu sanmıyorum.

OTOH bu sadece yukarıdaki örnekte olduğu gibi önemsiz adımlar için geçerlidir. Aklımda aynı anda tutamayacağım ve / veya sonuçtan% 110 emin olamadığım daha karmaşık bir şey için, her seferinde bir adım atmayı tercih ediyorum.


1

TDD yolunu ilk kez belirlerken, adımların boyutu bu sorunun gösterdiği gibi kafa karıştırıcı bir sorun olabilir. Test odaklı uygulamaları yazmaya başladığımda kendime sıkça sorduğum sorular; Yazdığım test uygulama geliştirmeme yardımcı oluyor mu? Bu önemsiz ve bazıları ile ilgisiz görünebilir ancak bir anlığına benimle birlikte orada kalın.

Şimdi herhangi bir uygulama yazmaya başladığımda genellikle bir teste başlayacağım. Bu testin ne kadar büyük bir adım olduğunu, ne yapmaya çalıştığımı anladığımla ilgilidir. Kafamda bir sınıfın davranışını hemen hemen gördüğümü düşünüyorsanız, adım büyük olacaktır. Çözmeye çalıştığım sorun çok daha az netse, adım sadece X adında bir yönteme gideceğini ve Y değerini döndüreceğini bilmek olabilir. Bu noktada yöntemde herhangi bir parametre olmaz Yöntemin adının ve iade türünün değişme ihtimali vardır. Her iki durumda da testler gelişimimi zorluyor. Bana başvurum hakkında bazı şeyler söylüyorlar:

Kafamda olan bu sınıf gerçekten işe yarayacak mı?

veya

Bu şeyi nasıl yapacağım ben?

Mesele şu ki, göz açıp kapayıncaya kadar büyük adımlar ve küçük adımlar arasında geçiş yapabiliyorum. Mesela eğer büyük bir adım işe yaramazsa ve etrafındaki bariz bir yolu göremiyorsam daha küçük bir adıma geçeceğim. Bu işe yaramazsa, daha küçük bir adıma geçeceğim. O zaman gerçekten sıkışırsam üçgenleme gibi başka teknikler de var.

Benim gibi bir geliştiricisin ve testçi değilsin, o zaman TDD kullanmanın amacı test yazmak değil kod yazmak. Size herhangi bir fayda sağlanmadıkça küçük testler yazmaktan kaçının.

Umarım TDD ile bir çalışmanın tadını çıkardın. IMHO eğer teste daha fazla insan bulaşmışsa dünya daha iyi bir yer olurdu :)


1

Birim testine ilişkin bir primerde, aynı yaklaşımı okudum (gerçekten, gerçekten çok küçük görünen adımlar) ve şöyle sevdim (şöyle düştü) olan bir şeyi “ne kadar küçük olmalılar” sorusunun cevabı olarak:

Bu, adımların işe yaradığından ne kadar emin olduğunuzla ilgilidir. İsterseniz çok büyük adımlar atabilirsiniz. Ancak, sadece bir süre deneyin ve kabul ettiğiniz yerlerde çok yanlış yönlendirilmiş bir güven bulacaksınız. Bu nedenle, testler gerçeğe dayalı bir güven oluşturmanıza yardımcı olur.

Belki meslektaşın biraz utangaçtır :)


1

Testin başarılı olması koşuluyla, yöntemin uygulanmasının asıl amacı bu değil midir? Testlerin genişletilmesi, ikinci örnekte daha hızlı başarısız olur, ancak her iki durumda da başarısız olmak için yapılabilir.


1
Vaktinizi boşa harcamakla ilgilenmiyorsanız, bu hiç önemli değil
SiberianGuy

1

En basit uygulama olmadığını söyleyen insanlarla aynı fikirdeyim.

Metodolojinin bu kadar katı olmasının nedeni, sizi mümkün olduğunca ilgili testler yazmak zorunda bırakmasıdır. Çünkü bir test durumu için sabit bir değer dönen ve bu bir seferde çağıran gayet zorlar geri dönüp gerçekten programdan saçma dışında başka bir şey almak için istediğini belirtmenizi. Bu kadar önemsiz bir vaka kullanmak, bazı bakımlardan kendinizi ayağınızdan vuruyor, ancak ilke, 'çok fazla' yapmaya çalıştığınızda hataların şartnamenizdeki boşluklara sürünmesi ve mümkün olan en basit uygulamaya gereksinimi ortaya koymasıdır. Test, gerçekte istediğiniz davranışların her biri için yazılmalıdır.


"Sabit bir değer döndürme" ile ilgili bir güncelleme ekledim
SiberianGuy
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.