TDD yaparken neden tüm testleri tek seferde yazmıyorsunuz?


54

TDD için Kırmızı - Yeşil - Refaktör döngüsü iyi kurulmuş ve kabul edilmiştir. Bir tane başarısız ünite testi yazarız ve mümkün olduğunca basit bir şekilde geçmesini sağlarız . Bir sınıf için birçok başarısız ünite testi yazmanın ve hepsini bir seferde geçmenin bu yaklaşımın faydaları nelerdir ?

Test paketi sizi hala yanlış kod yazmaya veya yeniden ateşleme aşamasında hata yapmaya karşı korur, bu nedenle zararı nedir? Bazen bir sınıfa (veya modüle) yönelik tüm testleri bir kerede beklenen tüm davranışları hızlıca yazmak için bir 'beyin dökümü' olarak yazmak daha kolaydır.


20
Sizin için en iyisini yapın (bazı deneylerden sonra). Körü körüne takip etmek dogma asla iyi bir şey değildir.
Michael Borgwardt

6
Tüm testlerinizi bir kerede yazmanızın, tüm uygulama kodunuzu bir kerede yazmak gibi olduğunu farz ediyorum .
Michael Haren

1
@MichaelHaren Bir sınıf (veya fonksiyonel modül) için tüm testler, karışıklık için özür dilerim
RichK

3
"Beyin dökümü" sorununa değinmek: Bazen birkaç farklı spesifik girdi testine ihtiyaç duyduğunuzu fark ettiğinizde test / kodlamada bazı noktalar vardır ve dikkatinizi dağıtmadan önce bu aydınlanmanın netliğinden faydalanmak isteme eğilimi vardır. kodlamanın küçümsemesi. Bunu genellikle ayrı bir liste (örn. Mylyn) ya da Test sınıfında test etmeyi hatırlamak istediğim (örn. // boş vakası) yorumların bulunduğu bir yorum listesi yaparak yönetirim. Ancak, her seferinde yalnızca bir testi hala kodluyorum ve bunun yerine listeyi sistematik olarak kullanıyorum.
Sam Goldberg

1
iyi hiç kimse bu sözü niye bilmiyorum ama CAN NOT seferde tüm testleri yazmak. Tüm testleri elden önce yazmak BDUF ile aynıdır . Ve tarih bize BDUF hakkında ne öğretti? Bu neredeyse hiç çalışır.
Songo

Yanıtlar:


49

Teste dayalı tasarım, kodunuzu değil API'nizi doğru yapmakla ilgilidir.

İlk önce en basit başarısızlık testlerini yazmanın faydası, API'nizi (esasen anında tasarlarsınız) mümkün olduğunca basit hale getirmenizdir. Ön ödeme.

Gelecekteki kullanımları (yazacağınız bir sonraki testler), daha karmaşık durumlarla başa çıkabilmek için en iyi tasarımdan ziyade basit tasarımdan başlayacaktır.


Mükemmel puanlar! Bazen kodu test etmeye o kadar içindeyiz ki, ilk testinizi bile yazmadan önce API ve etki alanı modelinin ne kadar önemli olduğunu görmezden geliyoruz.
maple_shaft

Aslında Test Odaklı Gelişmenin amacına yönelik olarak +1 .
Joshua Drake

76

Eğer yazarken bir testi, sen konsantre bir şey.
Birçok testle dikkatinizi birçok işe yayıyorsunuz, bu yüzden iyi bir fikir değil.


8
Bunu kim düşürecek?
CaffGeek

6
@Chad aşağı oy değildi, ama bu cevabın bariz şekilde ıskaladığına inanıyorum. Test Odaklı geliştirme, Test (ler) i kodun tasarımını yürütmek için kullanmakla ilgilidir. Testi sadece test edilebilirlik için değil, tasarımı geliştirmek için ayrı ayrı yazıyorsunuz. Sadece test eserleri hakkında olsaydı, o zaman bu iyi bir cevap olurdu, ancak bazı önemli bilgiler eksik.
Joshua Drake

7
Bunu reddetmedim ama; Hakkında düşündüm. Karmaşık bir sorunun cevabı çok kısa.
Mark Weston

2
Bir seferde bir şeye konsantre olmak için +1, çoklu görev yapabilme kabiliyetimiz abartılıyor.
cctan

İşe yarayabilecek en basit cevap bu.
DNA

26

Birim testleri yazarken karşılaşılan zorluklardan biri, kod yazmanız ve kendi başına potansiyel olarak hataya açık olabilir. Uygulama kodunuzu yazarken yeniden yapılanma çabası sonucunda testlerinizi daha sonra değiştirmeniz gerekebilir. TDD ile bu, potansiyel olarak testlerinizden biraz fazla uzaklaşmanıza ve uygulamanızın proje süresince olgunlaştıkça birçok "denenmemiş" test kodunu yeniden yazmak için kendinize ihtiyaç duyduğunuzu gösterir. Bu tür bir problemden kaçınmanın bir yolu, bir seferde tek bir şeyi yapmaya odaklanmaktır. Bu, değişikliklerin testleriniz üzerindeki etkisini en aza indirmenizi sağlar.

Elbette, bu büyük ölçüde test kodunuzu nasıl yazdığınıza bağlı olacaktır. Her bireysel yöntem için bir birim testi mi yazıyorsunuz veya özelliklere / gereksinimlere / davranışlara odaklanan testler mi yazıyorsunuz? Diğer bir yaklaşım, Behavior Driven yaklaşımını uygun bir çerçeveyle kullanmak ve testler spesifikasyonlarmış gibi yazmaya odaklanmak olabilir. Bu, TDD'ye daha resmi bir şekilde bağlı kalmak istiyorsanız, BDD yöntemini benimsemek veya BDD testini uyarlamak anlamına gelir. Alternatif olarak, tamamen TDD paradigmasına sadık kalabilirsiniz, ancak testleri yazma biçiminizi değiştirebilir, böylece tamamen tek tek test yöntemlerine odaklanmak yerine, uyguladığınız gerekliliklerin özelliklerini karşılamak için davranışları daha genel olarak test edebilirsiniz.

Aldığınız spesifik yaklaşımdan bağımsız olarak, yukarıda açıkladığım tüm durumlarda, ilk önce bir test yaklaşımı kullanıyorsunuzdur, bu nedenle beyninizi güzel bir test odasına indirmek cazip gelse de, daha fazlasını yapmak için günaha kesinlikle gerekli. Ne zaman yeni bir test paketi başlatmak üzereysem, YAGNI'yi kendime tekrarlamaya başlıyorum ve bazen derhal önemli olan konuya odaklanmamı hatırlatmak ve sadece istediklerimi tatmin etmek için gereken minimumları yapmak için kodumda bir yoruma bile atıyorum. Özelliğin gereklerini uygulamak üzereyim. Red-Green-Refactor'a yapıştırmak, bunu yapmanıza yardımcı olur.


Test kodunun nasıl yazıldığına dikkat çektiğinize sevindim. Bazıları tek bir fonksiyon veya yönteme girdilerin her gerçekçi olasılığını kapsayan tek bir ana ünite testi yazmak gibi. Diğerleri birim testleri ile daha BDD yaklaşımı benimsiyor. Bu ayrım, bütün bir test paketi yazmanın önemli olup olmadığının mutlaka kötü bir uygulama olup olmadığına karar verirken önemlidir. Harika fikir!
maple_shaft

17

Bunu yaparak TDD sürecini kaçırdığınızı düşünüyorum . Sadece başlangıçta tüm testlerinizi yazarak TDD kullanarak geliştirme sürecinden gerçekten geçmiyorsunuz. Hangi testlere ihtiyaç duyacağınızı basitçe tahmin edersiniz. Bu, kodunuzu geliştirirken bir kerede bir tane yaparsanız, yazdığınız testlerden çok farklı bir test seti olacaktır. (Programınız doğada önemsiz olmayacaksa.)


1
İş ve işletme uygulamalarının çoğu, doğası gereği teknik açıdan önemsizdir ve uygulamaların çoğunun işletme ve işletme olarak görülmesi nedeniyle, çoğu uygulama da doğa açısından önemsizdir.
maple_shaft

5
@maple_shaft - teknoloji önemsiz olabilir, ancak iş kuralları değildir. Her biri farklı gereksinimleri olan 5 yönetici için bir uygulama kurmayı deneyin ve basit, zarif, daha az, minimalizm tasarımınızla ilgili bazı BS'leri dinlemeyi reddediyor.
JeffO

5
@JeffO 1) BS değil. 2) Zarif bir minimalist tasarım, iyi bir yazılım geliştirme becerisi gerektirir. 3) Haftada 5 dakikadan fazla zamanınız olmayan 5 farklı yöneticinin gereksinimlerinizi sizin için harcamak ve hala minimalist bir tasarıma sahip olmak için azaltılması yeteneği mükemmel bir yazılım geliştiricisi gerektirir . Profesyonel İpucu: Yazılım geliştirme, kodlama becerilerinden daha fazlasıdır, müzakere, konuşma ve sahip olmadır. Alfa köpeği olmalısın ve bazen ısırmalısın.
maple_shaft

1
Doğru anlarsam, bu cevap soruya yalvarıyor.
Konrad Rudolph

1
@maple_shaft Jeff O'nun yorumuyla yaptığı şey buydu, değil mi?
ZweiBlumen

10

"Beyin fırtınası" sırasında önümde düşünebildiğim tüm testleri “yazıyorum”, ancak her testi testi açıklayan tek bir yorum olarak yazıyorum .

Sonra bir sınama kodunu dönüştürmek ve işi yapmak, böylece derlemek ve geçmek . Genelde, düşündüğüm tüm testlere ihtiyacım olmadığına karar veriyorum veya farklı testlere ihtiyacım var, bu bilgiler yalnızca testleri geçmek için kod yazarak geliyor.

Buradaki sorun, test yöntemini oluşturmadan ve test ettiği sınıfları bulana kadar kod yazamayacağınızdır; aksi halde aynı anda tek bir testte çalışmanıza yol açan birçok derleyici hatası alırsınız.

Şimdi, testler “İngilizce” olarak yazılırken, belirli bir akış gibi bir sistem kullanıyorsanız, müşterilerin sadece bir test oluşturmak yerine zamanlarını alırken bir dizi teste katılmalarını isteyebilirsiniz.


1
Evet, ilk önce tüm testlerinizi kodlamakla ilgili sorunlara işaret eden yukarıdaki cevapları kabul ederken, mevcut yöntemin herhangi bir kod olmadan bir test tanımları kümesi olarak nasıl davranması gerektiğine dair genel bir anlam vermemeyi çok yararlı buluyorum. Bunları yazma süreci, yazmak üzere olduğum kodun neyin gerekli olduğunu tamamen anlayıp anlamadığımı ve hakkında düşünmediğim son durumların olup olmadığını netleştirme eğilimindedir. İlk testi kodlarken kendimi çok daha rahat buluyorum ve daha sonra yöntemin nasıl çalışması gerektiğiyle ilgili "genel bakış" ı belirttikten sonra geçmesini sağlıyorum.
Mark Weston

10

TDD'nin ardındaki fikir hızlı yinelemedir.

Kodunuzu yazmak zorunda kalmadan önce yazmanız gereken büyük test bölümleriniz varsa, tekrar tekrar kodunuzu yeniden yazmak zorlaşır.

Kolay kod yeniden düzenlemesi olmadan TDD'nin sağladığı avantajların çoğunu kaybedersiniz.


5

TDD ile olan (sınırlı) deneyimime göre, her seferinde bir test yazma disiplinini her kırdığımda, her şeyin kötü gittiğini söyleyebilirim . Düşmesi kolay bir tuzak. “Ah, bu yöntem önemsiz”, kendi kendine düşünüyorsun, bu yüzden diğer iki ilgili testten vazgeçip devam edeceğim. Öyleyse tahmin et? Hiçbir şey göründüğü kadar önemsiz değildir. Bu tuzağa her girdiğimde , kolay olduğunu düşündüğüm bir şeyde hata ayıklamaya başladım , ancak garip köşe davaları olduğu ortaya çıktı. Aynı anda birkaç test yazmaya başladığımdan beri, böceğin nerede olduğunu bulmak çok işti.

Beyin hakkında bir bilgi birikimine ihtiyacınız varsa, birçok seçeneğiniz vardır:

  • Beyaz tahta
  • Kullanıcı hikayeleri
  • Yorumlar
  • İyi kalem ve kağıt

Bu listede hiçbir yerde derleyici olduğuna dikkat edin. :-)


5

Kodunuzu yazmadan önce neye benzeyeceğini bildiğinizi varsayıyorsunuz. TDD / BDD, bir QA işlemi olduğu kadar bir tasarım / keşif sürecidir. Belirli bir özellik için, özelliğin yerine getirildiğini doğrulayan en basit testi yazarsınız (bazen bir özelliğin karmaşıklığı nedeniyle bu gerekli olabilir). Yazdığınız ilk test, çalışma kodunun neye benzeyeceğine ilişkin varsayımlarla yüklenmiştir. Test grubunun tamamını, onu desteklemek için ilk kod satırını yazmadan önce yazarsanız, doğrulanmamış varsayımların bir likidini yapıyorsunuzdur. Bunun yerine, bir varsayım yazın ve doğrulayın. O zaman bir sonrakini yaz. Bir sonraki varsayımı doğrulama sürecinde, daha önceki bir varsayımı bozabilirsiniz, bu nedenle geri dönmeniz ve ya gerçekliğe uygun ilk varsayımı değiştirmeniz ya da ilk varsayımın geçerli olması için gerçeği değiştirmeniz gerekir.

Bilimsel bir defterde teori olarak yazdığınız her ünite testini düşünün. Not defterini doldururken teorilerinizi kanıtlar ve yenilerini oluşturursunuz. Bazen yeni bir teoriyi kanıtlamak önceki bir teoriyi doğrular, bu yüzden bunu düzeltmelisin. Bir kerede bir teoriyi ispat etmek, bir kerede 20 demeyi ispatlamaya çalışmaktan daha kolaydır.


TDD, kodunuzu daha küçük parçalarda yazmadan önce nasıl görüneceğini bildiğinizi varsayar.
Michael Shaw,

4

TDD (deneyimlerime göre) gerçek dünyadaki gelişim yollarına daha iyi uyan, oldukça yinelemeli bir yaklaşımdır. Genellikle benim uygulama bu süreçte kademeli olarak şekillenir ve her adım test için daha fazla soru, görüş ve fikir getirebilir. Bu, aklımı asıl işe odaklanmış tutmak için idealdir ve çok verimlidir, çünkü herhangi bir zamanda yalnızca kısa süreli bellekte sınırlı sayıda şeyi tutmam gerekir. Bu da hata olasılığını azaltır.

Fikriniz temel olarak IMHO'nun ele alınması daha zor olan ve daha fazla israf edebilen bir Büyük Test Up Front yaklaşımıdır. Çalışmanızın ortasında, yaklaşımınızın iyi olmadığını, API'nizin kusurlu olduğunu ve baştan başlamanız veya bunun yerine bir üçüncü taraf kütüphanesi kullanmanız gerektiğinin farkına varırsanız ne olur? Daha sonra testlerinizi yazmak için yapılan çalışmaların çoğu boşa harcanıyor.

Bu senin için işe yararsa, tamam dedi. Sabit, ayrıntılı bir teknik şartnameyle çalışıyorsanız, yakından tecrübe ettiğiniz bir alanda ve / veya oldukça küçük bir görevde çalışıyorsanız, gerekli test durumlarının çoğunu veya tamamını hazırladığınızı ve uygulamanızın şu anda neticesinde açık olduğunu hayal edebiliyorum. başlangıç. O zaman tüm testleri bir kerede yazarak başlamak mantıklı olabilir. Deneyiminiz bu sizi uzun vadede daha üretken kılıyorsa, rulebook'lar için çok fazla endişelenmenize gerek yok :-)


4

Sadece bir şeyi düşünmenin ötesinde, TDD'nin bir paradigması testi geçmek için mümkün olan en az kodu yazmaktır. Bir seferde bir test yazdığınızda, bu testi geçmek için yalnızca yeterli kod yazma yolunu görmek çok daha kolaydır. Başarılı bir test paketi ile küçük adımlarla koda girmiyorsunuz, hepsini bir seferde geçmeleri için büyük bir adım atmanız gerekiyor.

Şimdi, hepsini "tek seferde" geçmesi için kod yazmanızla sınırlı tutmuyorsanız, fakat bir seferde bir testi geçecek kadar kod yazmanız yeterli olabilir. Sadece devam etmek ve ihtiyaç duyduğunuzdan daha fazla kod yazmak için daha fazla disipline sahip olmalısınız. Bu yolu başlattığınızda, kendinizi en azından bir test tarafından yönlendirilmediği ve belki de gerekmediği anlamında denenmeyen testlerden daha fazla kod yazmaya açık bırakıyorsunuz. (veya uygulandı) herhangi bir testle.

Yöntemin ne yapması gerektiğinin azaltılması, yorumlar, hikayeler, işlevsel bir özellik, vb. Kesinlikle kabul edilebilir. Bunları bir seferde bir kez testlere çevirmek için beklerdim.

Testleri bir kerede yazarak özleyebileceğiniz bir diğer şey, testi geçmenin sizden diğer test durumlarını düşünmenizi isteyebileceği düşünme sürecidir. Mevcut testlerin bir bankası olmadan, son test bağlamında bir sonraki test senaryosunu düşünmeniz gerekir. Dediğim gibi, yöntemin ne yapması gerektiği hakkında iyi bir fikir sahibi olmak çok iyi, ama çoğu zaman kendimi bir priori olarak kabul etmediğim, ancak sadece yazma sürecinde meydana gelen yeni olasılıklar bulduğumda buldum. testleri. Özellikle sahip olmadığım hangi yeni sınavları yazabileceğimi düşünme alışkanlığınız yoksa, bunları kaçırmanız tehlikesi var.


3

(Başarısız) testlerini yazan geliştiricilerin, geçmeleri için gerekli kodu uygulayan geliştiricilerin farklı olduğu bir proje üzerinde çalıştım ve gerçekten etkili buldum.

Bu durumda, yalnızca geçerli yinelemeyle ilgili testler bir kez yazılmıştır. Öyleyse önerdiğiniz şey bu tür bir senaryoda mükemmel bir şekilde mümkün.


2
  • Sonra bir seferde çok fazla şeye konsantre olmaya çalışırsın.
  • Tüm testleri geçmek için uygularken uygulamanızın çalışan bir sürümüne sahip değilsiniz. Çok fazla uygulama yapmanız gerekiyorsa, uzun zamandır çalışma sürümünüz olmayacak.

2

Kırmızı-Yeşil-Refaktör döngüsü, TDD'de yeni geliştiriciler için tasarlanmış bir kontrol listesidir. Ne zaman izleyeceğinizi ve ne zaman kırabileceğinizi bilene kadar (yani, bu soruyu stackoverflow'ta sormak zorunda kalmayacaksınız :) bilmeden bu kontrol listesini takip etmenin iyi bir fikir olduğunu söyleyebilirim :)

TDD'yi on yıla yakın bir süredir yaptıktan sonra, üretim kodunu yazmadan önce çok nadiren testler yazdığımı söyleyebilirim.


1

Bazı dış paydaşların çalıştırılabilir bir özelliği olan BDD'yi tarif ediyorsunuz. Önceden belirlenmiş bir ön şartname varsa (örneğin, bir format spesifikasyonu, endüstriyel standart veya programcının alan uzmanı olmadığı durumlarda) bu faydalı olabilir.

Bu durumda normal yaklaşım, proje yöneticisi ve müşteri tarafından görülen ilerlemedir ve giderek daha fazla kabul testini kapsamalıdır.

Bu testler genellikle Salatalık, Sporcu veya benzeri bir BDD çerçevesinde belirtilmiş ve yürütülmüştür.

Bununla birlikte, birim testlerinizle karıştırdığınız, nitrat kumlama uygulama detaylarına çok fazla API ile ilgili son durum, daha başlangıçta test niteliğindeki bir uygulama artefaktı olan maddeye odaklanan başlatma konularına daha yakın olan bir şey değildir .

Kırmızı-yeşil-refactor disiplininin pek çok faydası vardır ve bunları önceden yazarak ümit edebileceğiniz tek şey bile kırmaktır.


1

Zamanında bir test: ana avantaj, bir şeye odaklanmaktır. Derinlik ilk tasarım düşünün: hızlı geri bildirim döngüsü ile derin gidebilir ve odaklanmış kalabilirsiniz. Yine de bütün sorunun kapsamını kaçırabilirsin! Yeniden yapılanmanın devreye girdiği an budur (büyük). Onsuz TDD çalışmıyor.

Tüm testler: analiz ve tasarım, sorunun kapsamını daha fazla ortaya çıkarabilir. Genişlik birinci tasarım düşünün. Sorunu daha fazla açıdan analiz ediyor ve deneyimden girdi katıyorsunuz. Doğası gereği daha zor, ancak 'sadece yeterince' yaparsanız ilginç yarar - daha az refaktasyon - getirebilir. Fazla analiz etmenin kolay olduğu ve yine de işareti tamamen kaçırdığı konusunda dikkatli olun!

Birini ya da diğerini tercih etmeyi genellikle tavsiye etmekte güçlük çekiyorum çünkü faktörler çoktur: deneyim (özellikle aynı problemle), alan bilgisi ve becerileri, yeniden düzenleme kodunun dostu olması, sorunun karmaşıklığı ...

Sanırım tipik iş uygulamalarına daha dar odaklanırsak, en hızlı deneme yanılma yaklaşımı ile TDD genellikle etkinlik açısından kazanacaktı.


1

Test çerçevenizin bunu desteklediğini varsayarsak, önereceğim şey braindump yapmak istediğiniz testleri uygulamak yerine, daha sonra uygulayacağınız açıklayıcı bekleyen testleri yazmaktır. Örneğin, API’niz foo ve bar yapmalı ancak biz yapmamalıysa, test takımınız için aşağıdaki kodu ekleyin (bu örnek rspec’tedir), ardından birer birer saldırın. Düşüncelerinizi hızlı bir şekilde alırsınız ve tüm sorunlarınızı tek tek ele alırsınız. Tüm testler geçtiğinde, braindump sırasında sahip olduğunuz tüm sorunları çözdüğünüzü bileceksiniz.

describe "Your API" do

  it "should foo" do
    pending "braindump from 4/2"
  end

  it "should bar" do
    pending "braindump from 4/2"
  end

  it "should not biz" do
    pending "braindump from 4/2"
  end

end
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.