TDD: Doğru mu yapıyorum?


14

Ben yeni bir programcıyım (sadece yaklaşık bir yıldır öğreniyorum) ve daha iyi olma hedefimde TDD hakkında yeni öğrendim. Çok yararlı göründüğü için kullanma alışkanlığına girmek istedim. Doğru kullandığımdan emin olmak istedim.

Ben ne yapıyorum:

  1. İhtiyacım olan yeni bir yöntem düşünün.
  2. Bu yöntem için bir test oluşturun.
  3. Test başarısız.
  4. Yazma yöntemi.
  5. Geçiş testi.
  6. Refactor yöntemi.
  7. Tekrar et.

Bunu yazdığım HER yöntem için yapıyorum, rahatsız etmemem gereken bazı var mı? Daha sonra genellikle mevcut yöntemlerimi farklı bir şekilde veya durumda test etmenin bir yolunu düşünüyorum. Düşündüğüm bu yeni testleri yapmalı mıyım yoksa her yöntemin zaten kendi testi olduğundan rahatsız etmemeliyim? Kodumu test edebilir miyim sanırım bunu sormak benim ana endişe.

DÜZENLE

Ayrıca, bu sadece merak ettiğim bir şeydi. GUI yapmak gibi bir şey yaparken, TDD bu durumda gerekli olur mu? Şahsen, bunun için nasıl test yazacağımı düşünemiyorum.


5
Bunu zaten her şeyi test ettiklerini söyleyen deneyimli profesyonellerden çok daha iyi yapıyorsunuz (ama etmiyorsunuz).
yannis

Açıkladığınız şey TDD'nin Ruhu değil .

1
ATDD veya BDD'ye bakmak isteyebilirsiniz.
dietbuddha

Belki daha yüksek bir başlangıç ​​yapın - ihtiyacınız olan yeni bir modülü düşünün.

Yanıtlar:


16

Bir iş akışı olarak tanımladığınız şey bence TDD Ruhu değil .

Kent Becks'in Amazon'daki kitabının özeti şöyle diyor:

Basitçe, test odaklı geliştirme uygulama geliştirmedeki korkuyu ortadan kaldırmak içindir.Bazı korkular sağlıklı olmakla birlikte (genellikle programcılara "dikkatli olmalarını söyleyen bir vicdan olarak görülür"), yazar korkunun yan ürünlerinin yapıcı eleştiriyi ememeyen geçici, huysuz ve iletişimsiz programcıları içerdiğine inanmaktadır. Programlama ekipleri TDD'ye girdiğinde hemen olumlu sonuçlar alırlar. İşleriyle ilgili korkuyu ortadan kaldırırlar ve kendileriyle karşılaştıkları zor zorluklarla başa çıkmak için daha donanımlıdırlar. TDD geçici özellikleri ortadan kaldırır, programcılara iletişim kurmayı öğretir ve ekip üyelerini eleştiri aramaya teşvik eder. Kısacası, TDD'nin arkasındaki öneri, kodun sürekli olarak test edilmesi ve yeniden düzenlenmesi gerektiğidir.

Pratik TDD

Resmi otomatik Testler, özellikle Birim Testler her sınıftaki her yöntemin test edilmesi bir anti-model kadar kötüdür ve hiçbir şeyi test etmemektedir. Olması gereken bir denge var. Her setXXX/getXXXyöntem için birim testleri mi yazıyorsunuz , bunlar da yöntem!

Ayrıca Testler zamandan ve paradan tasarruf etmenize yardımcı olabilir, ancak geliştirilmeleri için zaman ve paraya mal olduklarını ve kod olduklarını unutmayın, bu nedenle bakımı için zaman ve paraya mal olurlar. Bakım eksikliğinden atrofi yaparlarsa, faydadan çok bir yükümlülük haline gelirler.

Bunun gibi her şey gibi, kendinizden başka kimsenin tanımlayamadığı bir denge vardır. Herhangi bir dogma her iki durumda da muhtemelen doğru daha yanlıştır.

İyi bir metrik, iş mantığı için kritik olan ve değişen gereksinimlere göre sık sık değiştirilen bir koddur. Bu şeyler, otomatikleştirilmiş, büyük bir yatırım getirisi olacak resmi testlere ihtiyaç duyar.

Bu şekilde çalışan birçok profesyonel dükkan bulmak için çok zorlanacaksınız. Basit bir duman testi yapıldıktan sonra tüm pratik amaçlar için asla değişmeyecek şeyleri test etmek için para harcamak iş mantıklı değildir. .getXXX/.setXXXYöntemler için resmi otomatik birim testleri yazmak , bunun tam bir zaman örneğidir.

Program testinin ikna edici bir şekilde hataların varlığını gösterebileceğine, ancak hiçbir zaman yokluklarını gösteremeyeceğine dikkat çekildiğinden beri yirmi yıldır. Bu iyi duyurulmuş sözleri dindar bir şekilde dile getirdikten sonra, yazılım mühendisi günün düzenine geri döner ve chrysocosmic saflaştırmayı geliştirmeye devam eden yury simyacısı gibi test stratejilerini geliştirmeye devam eder.

- Edsger W. Djikstra . (1988'de yazılmıştır, bu yüzden 4.5 yıla daha yakındır.)

Ayrıca bu cevaba bakınız .


1
Bu endişe duyduğum konu ile ilgili. Benim gibi her yöntemi test etmemem gerektiğini düşünüyordum ama emin değildim. Görünüşe göre TDD hakkında biraz daha okumam gerekebilir.
cgasser

@kevincline Çoğu zaman setXXX/getXXXhiç gerekli değildir :)
Chip

1
Bu önemsiz getXXX'i hatırladığınızda ve yanlış yaptığınızda veya getXXX'inize tembel yükleme uygulayıp yanlış yaptığınızda, bazen gerçekten alıcılarınızı test etmek istediğinizi bileceksiniz.
Frank Shearar

13

Çok yakınsın. Bu biraz farklı bir şekilde düşünmeyi deneyin.

  1. İhtiyacım olan yeni bir davranış düşünün.
  2. Bu davranış için bir test oluşturun.
  3. Test başarısız.
  4. Yeni bir yöntem yazın veya mevcut yöntemi genişletin.
  5. Geçiş testi.
  6. Refactor kodu.
  7. Tekrar et.

Her mülk için otomatik olarak alıcı ve ayarlayıcı oluşturmayın . Bütün bir yöntemi düşünmeyin ve tüm işlevleri kapsayacak şekilde testleri yazın . Sınıf içindeki özellikleri kapsüllemeye çalışın ve ihtiyacınız olan davranışı sağlamak için yöntemler yazın. Yöntemlerinizi önceden planlamak yerine iyi bir tasarıma dönüştürün. TDD'nin bir test süreci değil, bir tasarım süreci olduğunu unutmayın. Diğer tasarım süreçlerine göre avantajı, çöp kutusuna attığınız bir kağıt parçası yerine otomatik regresyon testi akışını geride bırakmaktır.

Ayrıca, Bob Amca'nın üç TDD kuralını hatırlayın .

  1. Başarısız bir birim test geçişi yapmadığı sürece herhangi bir üretim kodu yazmanıza izin verilmez.
  2. Başarısız olmak için yeterli olandan daha fazla birim testi yazmanıza izin verilmez; ve derleme hataları hatalardır.
  3. Arızalı bir birim testini geçmek için yeterli olandan daha fazla üretim kodu yazmanıza izin verilmez.

1
@Zexanima: Bir yıl sonra çoğumuzdan daha iyi gidiyorsun. Sadece sizi bir sonraki adıma yönlendirmeye çalışıyorum.
pdr

2
Bağlandığınız bu 3 kuralı düşünüyorum; göründüğü kadar pastoral, herkesin karşılaşacağı tüm üretim dükkanlarının% 99'unda son derece dogmatik ve son derece gerçekçi olmayan katıdır.

1
@FrankShearar ya da köktendinci bir aşırılık yanlısı ve toptancılığın göz ardı edilemez şekilde patlaması olarak görülebilir. Bu dogmatik tutumu olan dükkanlarda çalıştım, dogmayı tam anlamıyla aldılar ve noktayı kaçırdılar; gerçek kodlarının hiçbirini pratik bir şekilde test etmeyen testler yazmak ve sadece Alay ve Bağımlılık Enjeksiyon çerçevelerini en iyi neyin önemli olduğunu karıştırmak yeteneğini test etmek.

1
@pdr Bir şeyin Ruhu, o şeyin dogmatik resmileştirilmiş kanonizasyonuna taban tabana zıttır. Bir felsefeye sahip olmak ve onu bir dine çevirmek bir şeydir . TDD, siyah beyaz dogmatik dini terimlerden söz edilmediğinden daha fazladır . 3 kuralı O ses dogmatik ve sunum dini ve her duyulan alır olduğunu Testi, Test, Deney OP gibi birine, mantra, bunları almak anlamıyla ve iyiliği daha o nedenler daha zarar. Frank'e, kutuplaştırıcı ifadelerin nedene faydadan çok zarar verebileceğini söylemiştim.

2
Demek istediğim dogmatizmin bir şeyi müjde olarak körü körüne kabul etmesinden kaynaklanıyordu . Polarize edici ifadeyi alın, deneyin, sizi rahatlık alanınızdan çıkarmaya zorlayın. 3-nokta-ya hep ya hiç-aşırı uç yaklaşımı denemezseniz TDD'ye dahil olan ödünleşmeleri değerlendiremezsiniz, çünkü verileriniz olmayacaktır .
Frank Shearar

5

Başkalarının yanıtlarına ekleyebileceğiniz birkaç şey:

  1. Aşırı test gibi bir şey var. Birim testlerinizin mümkün olduğunca az örtüşmesini sağlamak istiyorsunuz. Aynı kod parçasında aynı koşulları doğrulayan birden fazla teste sahip olmanın bir anlamı yoktur. Öte yandan, üretim kodunuzu yeniden düzenlediğinizde ve bu bölümle çakışan birçok testiniz olduğunda, geri dönüp tüm bu testleri düzeltmeniz gerekecektir. Oysa örtüşmezlerse, bir değişiklik en fazla bir testi keser.

  2. Bir test yazmanın daha iyi bir yolunu düşündüğünüz için, oraya geri dönüp tekrar yazmaya başlamam. Bu, aynı sınıfı / işlevi yazmaya ve yeniden yazmaya devam eden bireylere geri dönüyor çünkü onu mükemmelleştirmeye çalışıyorlar. Asla mükemmel olmayacak, bu yüzden devam et. Daha iyi bir yöntem keşfettiğinizde, bunu zihninizin arkasında tutun (veya testin yorumlarına ekleyin). Bir dahaki sefere orada olduğunuzda ve yeni yola geçmenin hemen faydasını görüyorsunuz, bu yeniden düzenleme zamanı. Aksi takdirde, özellik yapılırsa ve devam ederseniz ve her şey çalışırsa, çalışır durumda bırakın.

  3. TDD, her işlevin test edilebilir olduğundan emin olmakla kalmayıp, anında değer sağlamaya odaklanır. İşlev eklerken, "istemcinin neye ihtiyacı olduğunu" sorarak başlayın. Ardından, müşteriye ihtiyaç duyduğu şeyi vermek için bir arayüz tanımlayın. Ardından, testi geçmek için ne gerekiyorsa uygulayın. TDD, genel işlevleri kodlamak ve her birini test etmek yerine neredeyse kullanım senaryolarını test etmek gibidir (tüm "ne olursa olsun" dahil).

  4. GUI kodunu test etmeyi sordunuz. "Humble Dialog" ve "MVVM" modellerine bakın. Her ikisinin de arkasındaki fikir, aslında kullanıcı arayüzüne özgü mantığı olmayan bir dizi "görünüm modeli" sınıfı oluşturmanızdır. Ancak, bu sınıflar genellikle kullanıcı arayüzünüzün bir parçası olan tüm iş mantığına sahip olacak ve bu sınıflar% 100 test edilebilir olmalıdır. Geriye kalan çok ince bir UI kabuğu ve evet, tipik olarak bu kabuk test kapsamı dışında bırakılır, ancak bu noktada neredeyse hiç mantığı olmamalıdır.

  5. Mevcut kodun büyük bir kısmına sahipseniz, diğer birkaç kişinin önerdiği gibi, kesinlikle her yerde birim testleri eklemeye başlamamalısınız. Sizi sonsuza dek sürecek ve istikrarlı olan ve yakın (ya da çok yakın olmayan) gelecekte değişmeyen sınıfların% 80'ine birim testleri eklemekten faydalanamayacaksınız. Ancak, yeni işler için, TDD geliştirmeyi ALL koduyla kullanmayı son derece yararlı buluyorum. İşiniz bittiğinde yalnızca otomatik testlere sahip bir paket ile değil, aynı zamanda gerçek gelişimin büyük faydaları vardır:

    • Test edilebilirliği göz önünde bulundurarak, daha az kuplajlı ve daha modüler bir kod yazacaksınız
    • Kamu sözleşmenizi herhangi bir şeyden önce düşünerek, daha temiz olan genel arayüzlerle sonuçlanacaksınız.
    • Kod yazarken, yeni işlevselliğin doğrulanması, tüm uygulamanızı çalıştırmaya ve yürütmeyi doğru yolda zorlamaya çalışmaya kıyasla milisaniye sürer. Ekibim, sadece doğru koşulların gerçekleşmesini sağlayamadığı için ONCE bile çalıştırılmayan hata işleme kodunu hala serbest bırakıyor. Daha sonra KG'de bu koşullar gerçekleştiğinde ne kadar zaman harcadığımız şaşırtıcı. Ve evet, bu kodun birçoğu "duman testi yapıldıktan sonra gelecekte çok fazla değişiklik için alan değil" olarak düşünürdü.

1

Test edilmeyen bazı yöntemler vardır, yani bu testler. Bununla birlikte, başlangıç ​​kodu yazıldıktan sonra sınır koşulları ve diğer değerler gibi bazı testler için eklenmesi gereken bir şey vardır, böylece tek bir yöntem üzerinde birden fazla test olabilir.

Kodunuzu aşırı sınayabilirsiniz, ancak bu genellikle birisinin yaptığınız gibi kulağa hoş gelmeyen girişlerin olası her permütasyonunu test etmek istediği yerdir. Örneğin, bir karakteri alan bir yönteminiz varsa, girilebilecek her olası değer için bir test yazar mısınız? Aşırı test etmeye gideceğiniz yer burası, IMO.


Ahh tamam. Yaptığım şey bu değil. Genellikle ilk testlerini yaptıktan sonra yöntemlerimi çizgiden aşağı doğru test edebileceğim farklı bir durum düşünürüm. Sadece bu 'ekstra' testlerin yapılmaya değdiğinden emin oldum ya da eğer yapıyorduysa.
cgasser

Yeterince küçük artışlarla çalışırsanız, genellikle testinizin gerçekten işe yaradığından emin olabilirsiniz . Başka bir deyişle, bir test başarısızlığı (doğru nedenden dolayı!) Kendi başına testi test eder. Ancak bu "makul düzeyde emin" düzeyi test edilen kod kadar yüksek olmayacaktır.
Frank Shearar

1

Genellikle doğru yapıyorsunuz.

Testler koddur. Bu yüzden testi geliştirebilirseniz, devam edin ve yeniden düzenleyin. Bir testin geliştirilebileceğini düşünüyorsanız devam edin ve değiştirin. Bir testi daha iyi bir testle değiştirmekten korkmayın.

Kodunuzu test etmenizi öneririm, kodun ne yaptığını nasıl yapması gerektiğini belirtmekten kaçının. Testler yöntemlerin sonuçlarına bakmalıdır. Bu, yeniden düzenleme konusunda yardımcı olacaktır. Bazı yöntemlerin açıkça test edilmesi gerekmez (yani basit alıcılar ve ayarlayıcılar), çünkü bunları diğer testlerin sonuçlarını doğrulamak için kullanacaksınız.


Getters ve setters için de testler yazıyordum, bu yüzden bu ipucu için teşekkürler. Bu bana bazı gereksiz işleri kurtaracak.
cgasser

"Bazı yöntemlerin açıkça test edilmesi gerekmez (örn. Basit alıcılar ve ayarlayıcılar)" - Bir alıcıyı ve ayarlayıcıyı asla kopyalayıp yapıştırmadınız ve arkasındaki alan adını değiştirmeyi unuttunuz mu? Basit kodla ilgili şey, basit testler gerektirmesidir - gerçekten ne kadar zaman kazanıyorsunuz?
pdr

Yöntemin test edilmediği anlamına gelmez. Sadece diğer yöntemlerin ayarlandığını doğrulayarak veya bir testin gerçek kurulumu sırasında kontrol edilir. Alıcı veya ayarlayıcı düzgün çalışmazsa, özellikler doğru ayarlanmadığı için test başarısız olur. Bunları dolaylı olarak ücretsiz olarak test ettirirsiniz.
Schleis

Getter ve setter testleri uzun sürmüyor, bu yüzden muhtemelen yapmaya devam edeceğim. Ancak, asla kodumu herhangi bir kopyalamak ve yapıştırmak, bu yüzden bu soruna çalışmaz.
cgasser

0

TDD hakkındaki düşüncem, takımın 'seç ve tıkla' tarzı geliştiricilerden oluşan bir dünya yaratmasıdır. Araçların her yöntem için bir test saplaması oluşturması, her yöntem için test yazmanız gerektiği anlamına gelmez. Bazı insanlar, TDD'yi BDD ('davranış odaklı gelişim)' olarak yeniden adlandırıyorlar; burada testler çok daha ayrıntılı ve her bir küçük yöntem değil sınıfın davranışını test etmeyi amaçlıyor.

Testlerinizi, sınıfın kullanılması amaçlanan şekilde test edecek şekilde tasarlarsanız, özellikle her bir yöntemden biraz daha fazla egzersiz yapan testler yazmaya başladığınızda, özellikle de bunların etkileşimini test etmeye başladığınızda, bazı faydalar elde etmeye başlarsınız. yöntemleri. Sanırım bunu yöntemlerden ziyade bir sınıf için test yazma olarak düşünebilirsiniz. Her durumda, birlikte nasıl kullanıldıklarına dair herhangi bir çelişki veya çatışma olmadığından emin olmak için yöntemlerin kombinasyonunu kullanan 'kabul testleri' yazmalısınız.

TDD'yi testlerle karıştırmayın - öyle değil. TDD, yöntemleri test etmek için değil, gereksinimlerinizi uygulamak için kod yazmanız için tasarlanmıştır. Her yöntem için körü körüne test kodu yazan kişilerde genellikle kaybolan ince ama önemli bir noktadır. Yazdığınız kodun olması gerektiği gibi çalıştığından değil, kodunuzun yapmak istediğiniz şeyi yaptığından emin olmak için testler yazmanız gerekir.

BDD v TDD hakkında sağda bazı iyi bağlantılar var. Onları kontrol et.


0

Ne zaman başlar TDD öğrenme, evet, körlemesine başarısız deneme geçiş yapmak dışında tek bir kod satırı yazmadan ve başarısız bir testin sadece yeterince yazmıyor dogmatik yaklaşımı takip (ve sağ / beklenen bir nedenle başarısız) olmalıdır .

TDD'nin ne hakkında olduğunu öğrendikten sonra, bazı şeylerin test edilmeye değmeyeceğine karar verebilirsiniz. Bu, her şey için izlemeniz gereken yaklaşımdır ve Japon dövüş sanatları buna " shuhari " der . (Bağlantı aynı zamanda bir öğretmen olmadan öğrenmenin aşamalarında nasıl ilerleyebileceğini de açıklıyor; şüpheliyim, çoğu insanın nasıl öğrenmek zorunda olduğu.)


0

İnanıyorum ki sen aşırıya kaçıyorsun.

TDD'yi yıllardır uyguluyorum ve tecrübelerime göre TDD etkili bir şekilde gerçekleştirildiğinde iki ana avantaj elde edersiniz:

  • Hızlı geri bildirim sağlayın
  • Yeniden düzenlemeyi etkinleştir

Hızlı geri bildirim sağlayın

Özellikle dinamik dillerle ilgili testleri bir saniyeden daha kısa sürede yapabilirim. Ve bir kaynak dosya diskte değiştirildiğinde bu testleri otomatik olarak çalıştıran dosya sistemi izleyicileri var. Bu yüzden testler için neredeyse hiç bekleme sürem yok ve hemen yazdığım kodun beklendiği gibi yapılıp yapılmadığını biliyorum. Böylece TDD çok verimli bir çalışma şekline yol açar.

Yeniden düzenlemeyi etkinleştir

İyi bir test paketiniz varsa, sistemin nasıl tasarlanması gerektiğine dair yeni bilgiler edindikçe güvenli bir şekilde yeniden düzenleyebilirsiniz.

İyi bir test paketi, kodunuzdaki sorumluluğu değiştirmenize ve kodun taşıma işleminden sonra beklendiği gibi çalıştığından emin olmanıza olanak tanır. Ve bunu test kodunda küçük değişikliklerle yapabilmelisiniz.

Sisteminizdeki her yöntem için testler yazarsanız, olasılıklar kodunuzu kolayca yeniden düzenleyemezsiniz, kodunuzun her bir yeniden düzenleyicisi test kodunda büyük değişiklikler gerektirecektir. Test kodunun hala beklendiği gibi çalıştığından emin olabilir misiniz? Yoksa test koduna yanlışlıkla bir hata mı eklediniz, sonuç olarak üretim kodunda bir hataya neden oldunuz mu?

Bununla birlikte, pdr'nin cevabında da önerildiği gibi , testler yazarken yöntemler yerine davranışa odaklanırsanız , sistemi yeniden düzenlerken çok daha az değişiklik gerektiren testlere sahip olursunuz.

Ya da Ian Cooper'ın bu sunumda söylediği gibi (bellekten alıntı yaptım, bu yüzden doğru şekilde alıntılanmayabilir):

Yeni bir test yazma nedeniniz yeni bir sınıf eklemek değil, yeni bir davranış eklemek olmalıdır


-2

Herkese açık her yöntemi test etmelisiniz .

Burada dikkat edilmesi gereken nokta, kamu yöntemleriniz çok küçükse, muhtemelen çok fazla bilgi açığa çıkarırsınız. Her mülkü getXXX()gerçekten kapsülleme olarak ifşa etmenin yaygın uygulaması .

Genel yöntemleriniz aslında sınıfın davranışıysa, bunları test etmelisiniz. Değilse, iyi kamu yöntemleri değildir.

EDIT: pdr'nin cevabı benimkinden çok daha eksiksiz.

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.