Neden test güdümlü geliştirme (TDD) ve geliştirme güdümlü test (DDT) hakkında çevik değil?


74

Bu yüzden çeviklik konusunda yeniyim ama test odaklı bir gelişme değil . Üniversitedeki profesörlerim testler ve sonra kodlar sonra testler hakkındaydı. Nedenini anladığımdan emin değilim. Benim bakış açıma göre, kodunuz geliştikçe büyük olasılıkla değişecek olan çok büyük bir maliyet.

TDD'yi böyle hayal ediyorum ve beni neden şaşırtıyor. TDD yüklenicisi olarak bir ev inşa etseydim.

  1. Bana tüm özelliklerini (hikayeleri) ver.

  2. Özellikleri onayı alın.

  3. Tüm özellikleri incelemeye ayırın, ihtiyacım olacağını düşünüyorum (geleceğe bakın).

  4. Bu noktalara bakmak için bir müfettiş çağırın ve bana şu anda denetimde başarısız olduğumu söyleyin (teşekkür ederim).

  5. Evi inşa etmeye başla.

  6. Müfettişi her gün geri ara (2/100'ü geç).

  7. Vur, benim anlayışımda bir sorun vardı ve şimdi 9 inceleme daha eklemeliyim ve bunlardan 27'sini değiştirmem gerekiyor.

  8. Müfettişi 1/109'u geçerek arayın.

  9. Lanet olsun. Müfettiş neden böyle bir şey yapmıyor ... oh bu yöntem adını güncelledim ...

  10. Biraz daha yap.

  11. UGGGGHHHH DAHA FAZLA DEĞİŞİKLİKLER lanet müfettişi güncellememe izin veriyor. Oh, hayır, başarısız olamıyorum.

  12. Henüz bitti mi?

Tamam, bu tuhaf olabilir, ama sadece tüm yöntemlerimi nasıl bilmem gerektiğini ve kodum gelene kadar işlerin nasıl çalışacağını bilmiyorum. Zamanın% 99'una geri dönüp bir ünite testini güncellemeliyim. Sadece geriye doğru görünüyor.

Daha uygun görünen, DDT veya geliştirme odaklı testler. Bu da toplumun unutmuş olduğu ama unutmuş gibi göründüğü bir şey.

Anladığım kadarıyla bir ev için DDT şöyle olurdu:

  1. Bana tüm özelliklerini (hikayeleri) ver.

  2. Şartnamelerin onayını alın ve dağıtın.

  3. Bir birim (temel) başlatın.

  4. Bazı zor mantıkların notlarını al.

  5. Başlamadan önce, bir sonraki ünite denetime tabi tutulur (bir test oluşturun).

  6. Bulunan herhangi bir sorunu düzeltin ve tekrar inceleyin.

  7. Onaylanan bu ünite bir sonrakine geçer.

Hepimiz dürüst olmak gerekirse, bu daha insancıl ve geliştirici ve iş odaklı değil mi? Değişiklikler daha hızlı yapılabiliyor ve TDD'nin yarattığı gibi görünmüyor.


60
Benim için göze batan bağlantı kesilmesi, onları geçmeye başlayan kodu yazmadan önce 100'den fazla başarısız testine sahip olabileceğiniz fikridir. @Telastyn'ın dediği gibi, bir seferde birkaç başarısız testten daha fazlası olmamalıdır. "Testler sonra Kod sonra Testi" yazılı anlamına gelmez tüm herhangi bir kod yazmadan önce uygulamanın testlerin.
Eric King,

33
Metaforlar bir antipattern! İnsanlar, endişelerinizi gidermek yerine neden metaforunuzun konuya uymadığını açıklamak için daha fazla zaman harcayacaklar. Bu durumda asıl endişeniz, tüm testleri önceden yazmak zorunda olduğunuzu düşünüyorsunuz .
JacquesB

21
Burada bir not olarak TDD, çevik projelerde yaygın olarak kullanılmaktadır, ancak çevik proje yönetimi ile çevik kalkınma uygulamaları arasında ayrım yapmanın önemli olduğunu düşünüyorum. İkisi arasında çok güçlü bir ilişki yok. Çoğu çevik geliştirme uygulamasını, proje metodolojisine bakılmaksızın veya tersi yönde kullanabilirsiniz. Sıklıkla, çevik olarak, çevik olarak yapmanız gereken şeylerin reçeteli bir listesini değil, en iyi sonucu elde etmek için yaklaşımınızı gerektiği gibi uyarlamakla ilgili olduğu unutulur. Başka bir deyişle, Agile! = Scrum + TDD.
JimmyJames,

35
Kayıt için, yazılım geliştirmeyi bir ev inşa etmekle karşılaştırmak anlamsızdır. Çalışmalar yapıldı. Sonuçlar açık. Cevap açık. Sadece bir ev inşa ettiğiniz gibi yazılım inşa etmiyorsunuz. . İki. Are. Farklı.
riwalk

14
Çevik tüm hızlı geribildirim döngüleri hakkındadır, TDD sadece belirli bir geri besleme döngüsü türüdür
jk.

Yanıtlar:


83

TDD yaklaşımının faydalarından biri ancak yeni tasarım yaptığınız zaman gerçekleşir.

İlk analojinizde, 100 test yazmazsınız, çünkü yazılımınızın nasıl görüneceğini bilmenin bir yolu yoktur.

Bir test yazarsın. Sen koş. Başarısız. Testinizi geçmek için en küçük kod birimini yazıyorsunuz. Sonra tekrar testini yaptın. Geçer.

Şimdi yukarıdaki işlemi tekrarlayarak bir sonraki testi yazınız.

Bu, başlangıçta, kodunuzun ne anlama geldiği açık olduğu zaman, israf edici bir yaklaşım gibi görünebilir, ancak bu yaklaşımın en iyi yanı, test kapsamınızın her zaman yüksek olduğu ve kod tasarımının bu şekilde daha temiz olmasıdır.

Bir yöntem olarak, çift programlama ile el ele gider; bir çift testi, sonraki testi geçmesi için kodunu, daha sonra bir sonraki testi vb. yazar.

Yeni bir sınıf yazarken bile bu yaklaşımı kullanırım; ilk test, sınıf kurucusunu başlatmak için yapılan bir çağrıdır. Ama henüz sınıfı yazmadım, bu yüzden başarısız oluyor. Sonra basit, boş sınıfı yazarım ve ilk sınavım geçer.

Zihniyete girdikten sonra, içinde olmamak ve “eski moda” yöntemi kodlamak çok zordur.

Bunu öğrenmek için iyi bir Çevik ortamda çalışmanızı veya daha iyi anlamak için birkaç iyi Çevik kitap (Temiz Kod ve Temiz Kodlayıcı her ikisi de çok iyidir) okumanızı öneririm.


46
"Acil Tasarım" terimi, testlerin başarılı olmasını sağlayarak bir yazılım tasarımını büyütebildiğinize benziyor. Yapamazsın
Robert Harvey,

28
@nerdlyist: Yine de tasarımı unutma. Hala yazılım tasarlamanız gerekiyor; iyi tasarım sadece doğal olarak kırmızı-yeşil-refactordan ortaya çıkmaz. TDD iyi tasarımı teşvik eder, ancak yaratmaz.
Robert Harvey,

19
@RobertHarvey, " Ortaya Çıkan Tasarım" terimi, testlerin geçmesini sağlayarak bir yazılım tasarımını büyütebiliyormuş gibi görünmenizi sağlar . Bunu sadece birkaç kez yaptıktan sonra, yapılabileceğini temin ederim.
David Arno,

12
@DavidArno: Elinizde bir gereksinim belirtimi ile başlıyor musunuz? Bu spesifikasyonu mantıklı bir mimariye nasıl çevirirsiniz? Her seferinde testlerle yeniden icat ediyor musunuz, yoksa önceki mimari prensipleriniz var mı? Kimse bunu körlemiyor; kodlarınızı daha test edilebilir hale getirmeye zorlamaktan başka, ilk önce testlerinizi yazmakla ilgili sihirli bir şey yok.
Robert Harvey,

45
@DavidArno İtirazınızın, deneyimli bir geliştirici / mimar olarak kendinize yeterince kredi vermemesinden kaynaklandığını düşünüyorum. X modülünün sezgisel olarak neye benzediğini zaten bildiğiniz için, testleriniz gelişiminizi iyi yönde yönlendirecektir. Tecrübeli olmayan bir geliştirici , test yazmadan önce bir modülün neye benzemesi gerektiği hakkında hiçbir sezgisel fikre sahip değildir .
svidgen,

86

Yazılım bir ev değil. Sezgi iyidir, ama her zaman doğru olmadığını anlayın.

Tüm özellikleri incelemeye ayırın, ihtiyacım olacağını düşünüyorum (geleceğe bakın).

Bu doğru değil. TDD'de, kodu nasıl kullanmak istediğinizi açıklıyorsunuz. Teknik özellikler şöyle diyor: "Girmesi gereken bir ev olmalı." Test daha sonra “Hey, topuzlu bir kapı istiyorum.” Der. Bu, geleceğe bir kapı kasası, düğme, tuş kilidi vb. (Ya da argüman böyle devam ederse) uygulanması ile başlamaktan çok daha az görülür.

Müfettişi her gün geri ara (2/100'ü geç).

Bu doğru değil. Ev için test yazmıyorsun. Ön kapı çerçevesi için testler yazıyorsun, sonra onları yeşil yapıyorsun. Ardından kapının sağlam olup olmadığını test eder ve onları yeşil yapar. Sen olmalıdır belki herhangi bir zamanda kırık en fazla bir düzine kadar testler. Genellikle, iki ile dört arasındadır.

Ayrıca, "müfettişi dışarıya çağır" benzetmesi, kişinin çıkıp işini yapması için biraz zaman aldığını gösterir. TDD yineleme için çalışan birim testleri tam anlamıyla birkaç saniye sürmelidir .

Değişiklikler daha hızlı yapılabilir ve genel TDD'siz yaratılmış gibi görünüyor.

Genel gider, düşündüğünüzden daha az. Testleri çalıştırmak için birkaç saniye, belki de yarım düzine kez yapmak, genel geliştirme süresi ile aynı değildir.

İlk önce dev problemi bazen test etmeye başladığınızda, büyük bir problemin olduğunu keşfedersiniz. Yatağı tuvaletin yanına koyuyorsun ve kimse orada bir sorun yaşamak istemiyor. Herhangi bir TDD ek yükünden daha uzun sürmesi gerekenler. TDD'nin yakalayacağı şeyler, çünkü TDD sizi kodunuzu en baştan kullanmaya zorlar ve onunla nasıl etkileşime gireceğini düşünür.

Üniversitedeki profesörlerim Testler fikri, sonra Kod ve ardından Test hakkındaydı.

Bütün bunlar, TDD'nin her yerde bulunmadığını söyledi. Birçok yer hala ilk önce birçok şey yapıyor ve TDD'nin öne sürdüğü faydaların çoğu abartılıyor. Önemli olan testleri yaptırıp onları iyi yapmak. İşi yapma sırası daha az önemli.


18
Sadece son paragraf için +1. Evinizdeki örnekler gerçekten ne kadar aptal "dini" nin olabileceğinin altını çiziyor.
Robert Harvey,

23
“Önemli olan, testleri yapmanız ve iyi hale getirmenizdir. İşinizi yapma sırası daha az önemlidir. ” Ben Test Odaklı Geliştirme'nin (TDD) büyük bir hayranıyım ve bunun için savunuculuğum var. Ancak kod yazmak dağınıktır. Daha zor, daha az iyi tanımlanmış problemler için, gerekliliklerin ne olduğunu anlamadan önce tipik olarak önce bazı kodları yazmam gerekir. Sonra gereksinimleri yazabilir ve sonra testleri yazabilirim.
Trevor Boyd Smith

1
@TrevorBoydSmith, belgeleri bu noktada gereklilikleri yazmazdınız.
nerdlyist,

8
TDD , kodun kullanıcısı perspektifini koyduğundan , [en iyi durumda] daha iyi arayüzler sağlar. Mesela open_dooraradığımda bir bayrak göndermemeliydim toilet_flushed; bu yüzden testimi bu şekilde yazmıyorum ve bu yüzden kodumda "kaba kenarlar" yok. Tamamen nasıl adlandırıldığına bakmadan tamamen yeterli bir şekilde yazılmış olan kodda genellikle garip arayüzler veya varsayımlar / ön koşullar bulunur.
brian_o

3
@TrevorBoydSmith bir isim koymak için, "Spike & Stabilize" adında bir şey olduğunu duydum ve evet, nasıl yapılacağını bilmediğiniz bir şeyi nasıl yapacağınızı keşfederken kullanışlı bir teknik.
RubberDuck

13

Fiziksel bir şey oluşturma ve yazılım yazma arasındaki benzerlikler oldukça az.

Bununla birlikte, işaret etmeye değer büyük bir ayrım var:

"Test yazma" ile "test yürütme" arasında bir fark vardır.

Bir ev inşa örneğinde, gereksinimler ve testler yapmak fiziksel kurulumları sona önce. Test takımının bölümleri sürekli olarak çalıştırılıyor - hatta birden fazla ajan tarafından bile! Oluşturucu 2x4'ü aldığında, derhal ve otomatik olarak üniteyi "2x4'ün nasıl bir ses çıkardığı" fikrine karşı "test eder". Aldıktan sonra gereksinimleri yazmaz; üzerinde önceden var olan kontrolleri yapıyor.

Aynı şekilde monte edilmiş bir duvar, bir elektrik kutusu, sıhhi tesisat vb. sürekli işteki herkesin eğitimli gözleri tarafından örtük ve otomatik olarak çalıştırılırlar . Müfettiş ziyaret ettiğinde başka bir önceden var olan test takımı yürütülür. Birimler önceden var olan bu testi geçmek için inşa edilmediyse , başarısız olurlar.

Ve aynı şekilde bir bütün olarak yapı için. Planlar inşa öncesi varlığını sürdürüyor. Yolun her adımında, mühendisler , inşaat tamamlandığında yapının nihayetinde test edileceği önceden var olan bir koşullara doğru çalışıyorlar .

Bununla birlikte, her fiziksel projenin büyük bir test takımı tarafından gelmesine gerek yoktur. Atölyenize gidip ahşabı bir oyuncak kutusu veya benzeri bir şey için bir araya getirmeye başlarsanız, sezginizin ve yaratıcılığınızın size rehberlik etmesine izin verin, bu zor bir TDD ahşap işleme değildir. Bu durumda, temel olarak medyanın fiziksel yasalarına ve işi doğrulamak için zorlu beklentilerinize güveniyorsunuzdur (yani, "derler ve çalışırsa iyi olur!").

Ve bu tamam. Her şeyin katı testlerden önce gelmesine gerek yoktur.

tl; Dr.

İnşaat olsa bile! = Yazma yazılımı: İnşaat, test odaklı bir şekilde çalışır. Her birim için "geçen" koşullar yapmak onların kurulumları sona önce.

"Testleri yürütme" ile "yazma testleri" ile ilişkilendirmeyin.

Her şeyin TDD olması gerekmez.


Kod alıyorum! = Fiziksel bir analoji. Ama bu aslında benim için biraz daha fazla temizler. Diğer yorumumun işaret ettiği gibi, bunun testin yaratılıp yaratılmadığını merak ediyorum; ilk önce geri dönme ve şimdi daha büyük değişiklikler yapma arzusunu engelliyor mu?
nerdlyist,

@nerdlyist Bir şekilde, evet. Ancak, eğer testleriniz “doğru” şeyleri kontrol ediyorsa, istediğiniz bir “hiyerarş” dır .
svidgen

4
Ev benzetmesine geri dönme: Müşteriniz aniden farklı bir kapı stilinde yer değiştirmek isterse ve aynı boyutlara sahip değilse, kapının etrafındaki ve açıklık boyutlarındaki gereksinimler değişecektir ve iş bu testleri değiştirmeyi gerektirir. "Uygulamanın değişmesi için gereken çalışmaları yansıtmalı. Ama, testlerin bir sürü olmaz vs kapı açma P% hava geçirmez açıp kapatmak, kilit ve olmalıdır kapatıldığında, "engel" olduğunu değişmez testlerin sürü ...: değiştirmek Fiziksel değişiklikler uygun şekilde .
svidgen

1
Tekrar + 1'leyebilseydim, bu son bit dikkate almak yararlı olur. Her şeyin bir teste ihtiyacı yok. Ayrıca, yeniden okumak bana TDD birim testlerini entegrasyon ve regresyon testleriyle karıştırdığımı düşündürdü. İşçilerin otomatik olarak test ettiği, denetçinin entegrasyon yaptığı birimlerdir ve daha büyük değişiklikler yaparken regresyon testi yapılır.
nerdlyist,

1
@nerdlyist Entegrasyon ve regresyon testleri de ilk olarak test yapılabilir. Bunu yapmak , "TDD dogmatistleri" geliştirme döngüsüne tam olarak uymuyor, ancak sonuç büyük ölçüde aynı: Son test edilebilecek kodla, en az yabancı kodla ve gerçekten iddia ettiklerini doğrulayan testlerle bitirdiniz. Kodu yazdıktan sonra test etmek , bu şeylerin herhangi birini veya tümünü tamamlamayı biraz zorlaştırabilir. Hiç imkansız değil, ama potansiyel olarak daha zor.
svidgen

11

Yazma yazılımının bir ev inşa etmeye benzer olduğuna dair saçma bir fikre inanma tuzağına düştünüz. Değil. Mimarların çizimlerini ve yapısal mühendis hesaplamalarını oluşturmaya daha çok benziyor.

Şimdi gerçek evlerde, mimar bu planları ön plana çıkarıyor. Sonra, inşaat yapmaya başlayan, sorunla karşılaşan, bir şeyleri değiştirmek, bina kontrolünü ele geçirmek, değişiklik isteyen vb. İnşaatçıları çağırırsınız. Sonunda, mimar geri gelir ve çizimlerini yansıtmak için sizden daha fazla ücret alır. ne oldu. Bu, işleri yapmak için berbat bir yoldur, ancak evlerin yapımı uzun zaman alır ve pahalıdır, bu yüzden pratik olan tek yol budur.

Yazılım mühendisliği için işler daha iyi. Evin binanın eşdeğeri, derleyicinin kodunuzu bir türden derlenmiş birime (kütüphane, uygulama, web uygulaması vb.) Dönüştürmesini sağlıyor. Bunu günde yüzlerce kez yapmak çok hızlı ve ucuz. Sonuç olarak, özellikler eklerken evi tekrar tekrar inşa etmek bir anlam ifade etmiyor ve sonunda test etmek için sadece müfettişi (KG) arayın. Bunun yerine, bu kontrolleri otomatik hale getirirseniz, denetçinin her yeniden yaptığınızda her şeyi yeniden incelemesini sağlayabilirsiniz.

İster sıkı TDD'yi, ister bazı kod yazma, daha sonra bazı testlerin test odaklı bir yaklaşımını takip edip etmediğiniz fark etmez. İlk yaklaşımı tercih ederim, ikincisi. Size uygun olanı seçin. Önemli olan, ilerledikçe bu çekleri yaratmanızdır. Kodu değiştirmek istediğinizde, bir şeyi değiştirdiğinizde başka bir yerde işlevselliğin kopması konusunda sizi uyaracak şekilde yardımcı olurlar.


1
Görüyorum ki Bina Denetimi ile başa
Jules

5
“Bu işleri yapmanın berbat bir yolu, ancak evlerin yapımı uzun zaman alıyor ve pahalı, bu yüzden tek pratik yol.”: Yazılımda çok hızlı bir şekilde yeniden kurabileceğiniz doğru, ancak tamamen yanlış yaparsanız Kararın başında, daha sonra büyük bir yeniden yazmak gerekebilir. Artımlı tasarım her zaman bu tür problemleri yakalamaz: kendinizi bir çıkmazda bulana kadar küçük adımlarla hareket edersiniz ve geri dönmeniz gerekir. Gümüş mermi yok.
Giorgio

2
@Giorgio - büyük yeniden yazma, tek kararların kodun birçok yerine yansıması nedeniyle gerçekleşir. Karar değiştiğinde, kod birçok yerde değişir. Sürekli yeniden düzenleme, kopyalamayı sıkarak ve tek bir kararı yansıtan kod miktarını sınırlayarak bu sorunu hafifletir. İyi test kapsamı sürekli yeniden düzenlemeyi destekler.
kevin cline

7

Öncelikle ve en önemlisi , önceden belirlenen maliyet, düşündüğünüz kadar yüksek değildir . Evet, test yapmak için hiç test yapmamaktan daha fazla zaman harcıyorsunuz. Ama eğer bir "testten sonra" metodunu kullanırsanız, gerçekte neyi boşa harcıyorsunuz? Diyelim ki TDD 10 saat, DDT 6 saat sürüyor. "Ekstra" peşin masraflarınız sadece 4 saattir. Şimdi% 90 kapsama alanı gibi bir kod ölçüsü veya gereksinimi uygularsanız, TDD ve DDT'niz maliyetlerde daha da yakınlaşacaktır.

TDD ile daha az buggy kodu yazacaksınız. Gereksinimleri bir test olarak dile getirmiş olsanız bile, günün sonunda, kodunuzun tam olarak ne yapmak istediğinizi yaptığını kanıtlayabilirsiniz. Şimdi belki yanlış bir şey yapmasını istediniz, ama bu değişiklik isteği olan bir hata değil. Bu önemli. Çalışan bir ürünü "satmak" daha kolaydır, ancak farklı / daha iyi çalışabilir, o zaman çalışmadığı algılanan bir ürünü satmaktır. TDD ile testi geçmek ve çalışma kodunu yazmak gerçekten imkansızdır. Gereksinimleri anlamadığınız ve yanlış yazdığınız ancak çalışma kodunuzu yazmanız mümkündür.

TDD, kod tabanının yaşlandıkça daha iyidir. Test paketi olmadan veya kötü uygulanmış bir uygulamala yeniden düzenlemeyi deneyin. Basit bir değişiklik bile böceklere neden olabilir. Kapsamı iyi olan bir test takımına sahip olmak, ürün geliştikçe olması gerektiği gibi çalışmaya devam etmesini sağlar. Ayrıca, çakışan iş kurallarının vurgulanmasına yardımcı olur (daha uzun sürelerde gerçekleşir).

İşe yaramadığını bilmiyorsun. Bir test paketi olmadan, kodunuzun düşündüğünüz gibi çalıştığını veya çalışıyor gibi göründüğünü bilmiyorsunuz.

var foo = function(in) {
    if(in == 0) {
      return true
    }
}

Şimdi uygulamanızın her yerinde aradığınız if(foo()){ doStuff() }foo düzeltirse ne olur?

var foo = function(in) {
    if(in === 0) {
      return true
    }
}

Siz de testlerinizi yeniden gözden geçirmeli ve KURUTMALIDIR . İyi bir test takımının bakımı zor değildir. İyi yazılmış atomik testlerle nadiren geri dönüp bir kerede 1-2'den fazlasını değiştirmek zorunda kaldım. Test takımında daha büyük değişiklikler olduğunda, bir şeylerin doğru olmadığı dev bir kırmızı bayraktır.

Tüm yöntemlerimı nasıl bilmem gerektiğini ve kodum gelene kadar işlerin nasıl çalışacağını bilmiyorum.

Peki, yapmamalısın. Bazı iş birimlerinin yapıldığını test eden bir test yazmanız gerekiyor. Muhtemelen bilemeyeceğiniz şeyleri test ediyor gibi hissediyorsanız o zaman çok büyük düşünüyorsunuz, VEYA testi çok küçük.

Örneğin, bir kapının kapandığını ve kilitlendiğini bilmeniz gerekir. Door.close () ve door.lock () testini yapardım ve kapı kilitlendiğinde bu door.open () işlevi false döndürür. Bu kadar. Eğer testleriniz door.lock () ise veri tabanına bir bayrak koyar. O zaman çok küçük test ediyorsun. Testin door.lock () 'un nasıl çalıştığını bilmesine gerek yok, sadece işe yarıyor.

Şimdi, tüm kapılar ve pencereler kilitlendiğinde house.isSecure () yazan bir test yazıyorsanız, doğru döner. Önce kapılara ya da pencerelere bakmadan önce çok büyük düşünüyorsunuz.

Son olarak, çok büyük bir iş birimine bakıyor olabilirsiniz . Gereksinimler listenizi aldığınızda, en küçük birim üzerinde çalışacak şekilde bunları düzenlemelisiniz. Sadece o ünite için testi, sonra kodu yazın, sonra durulayın ve tekrarlayın.

Temelde, TDD'nin nasıl çalışması gerektiği konusundaki anlayışınız (liste) kapalı. Asla 2/100 geçiş yapmamalısın. 1/1 geçme, sonra 2/2 geçme, sonra 3/3 geçme, sonra 4/4 geçme vb. Olmalıdır.

Sizin için gözden geçirilmiş bir liste

  1. Tüm özellikleri alın
  2. Bir şartname seçin
  3. Dene
  4. Kodla
  5. Dene
  6. Eğer testler başarılı olursa 7'ye geçin, 4'e gidin
  7. Tüm özellikleri yapmışsanız, 8’e gidin, 2’ye gidin.
  8. Tüketici ile ilgili özellikleri gözden geçirin ve gerektiğinde yeni özellikler ekleyin. Doğru yapılırsa, hiç bir testi değiştirmeniz gerekmez. Sadece yenilerini ekleyin. Bazen gereksinim toplama ayrılabilir ve önceki testlerle çakışan testler eklemeniz gerekir, ancak testleri nadiren değiştirmeniz gerekir.

2
Bu cevabı seviyorum, çünkü TDD'nin gerçek avantajlarını vurgulayarak eski kod tabanlarını yönetilebilir hale getiriyor. Bir projenin yalnızca yeşil alan aşamasında çalışan birçok kişi TDD'nin faydasını görmüyor çünkü bu sadece fazladan bir iş gibi görünüyor. Varolan bir kod tabanını yükseltmeniz ve sürdürmeniz gerektiğinde gerçekten işe yarar. Keşke okulda size bir proje verselerdi, o zaman çalışmaya başlar başlamaz bir sürü özellik değişikliği talep eder. Bu, gerçeği daha yakından yansıtacak ve TDD'nin değerini gösterecektir.
thomij

1
Ben de bu cevabı seviyorum. Testleri elle yürütmek için ne kadar zaman harcadığımızı gerçekten unutmadığımızı unutmayın: düzenleme, derleme, elle hata ayıklama, yineleme. TDD, bunun çoğunu otomatikleştiriyor.
Technophile

Bana burada atlayan şey, TDD'de bir birim testi yazarken, istemci işlevsellik özelliklerinin bir parçası için bir test yazmadığınızı, bunun için bir test yazdığınızı not etmeniz önemlidir. Sizin gibi bir ünite - bir programcı - beyninizde tanımlamışsınız, yani “bu sınıf X olduğunda bir olay düzenlemeli, bunun için bir test yapalım”. Bu belirsiz "testleriniz sizin tarzınız!" Zaten TDD'yi aldığınızda söylemler harikadır ancak döngüden başka birine yanıt verdiğinden daha fazla soru getirir.
Ant P,

4

Diğer cevapların eksik olduğunu hissettiğim bazı anahtarlar var.

Üç Avantaj

İlk olarak, hata maliyeti ve değişim maliyeti, yazılım ve bazı kuralların uygulamayabileceği bir ev arasında inanılmaz derecede farklıdır. Örneğin, fiziksel bir yapıyı test etmenin maliyeti o kadar yüksektir ki, testi boşa harcamamak için yüksek derecede güven duymanız gerekir. Yazılımla, 1 - 5 saniye içerisinde bir birim test takımı çalıştırabilirseniz, elimizde farklı seçeneklerimiz vardır.

İkinci olarak, test edilen kodu yazmadan önce başarısız olmasını beklediğiniz bir testi gerçekleştirmenin amacı, testin kendisini doğrulamaktır. Aptal ya da savurgan görünebileceğinden emin olun. Ancak, test edilen kod kırılmış olsa bile, her zaman geçecek şekilde yazılmış yeterince birim testi gördüm. Test edilen kodu yazdığınızda, elle test edip, sonra birim testini yazdığınızda bu kolayca olabilir. Bir birim testi yazarsanız, başarısız olduğunu görün, ardından geçmek için gereken kodu yazdığınızda ve geçtiğinde, testinizin sağlam olduğunu bilirsiniz. Test altındaki kod gerilerse, birim testinizin bunu yakalaması makul bir ihtimaldir.

Sıkça belirtilmeyen TDD'ye üçüncü bir avantaj, ortaya çıkan kod büyüklüğü ve karmaşıklığın genellikle daha küçük bir büyüklük sırası olmasıdır. Her zaman basit ve özlü bir kod tercih etmekten gurur duydum. TDD pratiği yapmaya başlayana kadar. TDD bana daha önce yapmış olacağımın aşırı kod olacağını gösterdi. Bu neden oluyor? Bir test yazdığınız için testi geçmesi için kod yazınız. Test geçtiğinde, bununla bitirdin. Bu zihin ayarındaysanız, yanlışlıkla "ekstra" kod yazmak zordur.

(Ekstra kod üzerinde çalıştığım bir üründe gözlemlediğim bir sorun oldu. Kimsenin istemediği koddan kaynaklanan ciddi sorunlar, ancak bazı geliştiriciler bunun harika olacağını düşündü.)

Maliyet analizi

Yani bazı yönlerden haklısın. Bir ev inşa ederken bu stratejiden kurtulamadık. Çok pahalı olurdu. Ancak yazılım bir ev değildir. Yazılım ucuz.

Bir ev ile bir benzetme, bir yazılım derleyicisine karşı evi bir araya getirme işidir.

TDD olmayan bir dünyada, geliştiriciler hala yineliyor. Bir kod -> derleme -> çalışma -> test döngüsünü takip ediyoruz. Şimdiden büyük ölçüde bir ev inşa etmekten sapan bir modeldeyiz. Eğer inşaat elemanlarınız bir kapı çerçevesi yaparlarsa, o zaman bir kapı yaparlarsa, o zaman kapı için çok büyük olduğu için çerçeveyi yeniden inşa etmek zorunda kalırsanız, bir maliyet problemi olacaktır. Böylece, her şeyi mükemmel almanızı sağlamak için daha fazla zaman harcarsınız. Programlamada çoğu proje saniyeler veya dakikalar içerisinde derlenebilir, bu nedenle erken bir şeyin kusurlu olup olmadığı önemli değildir. Önemsizce düşünmenin maliyeti zamandan önce önemlidir, genellikle yeniden derleme maliyetinden daha ağır basar. Böylece her zaman yeniden derleriz.

TDD aynı prensiptir, sadece test döndürülerek döner. Testler süper ucuza yapılabiliyorsa (hepsi saniyeler içinde çalışır), o zaman büyük resim üzerinden düşünme maliyeti, tek bir büyük patlama kodlama yinelemesinde mükemmel, genel çözüm yeniden yapılanmanın maliyetinden ağır basar.

Dışında...

Bu argümanların dayanmadığı programlamada bazı şeyler var. Mimarlığın amacı budur. Daha sonra değişmesi daha pahalı olacak ön endişeleri belirleyin ve planlayın. Örneğin, ihtiyaçlarınız düşünülmeden anında veri tabanı seçmez, inşa etmeye başlar ve daha sonra değiştirebileceğinizi iddia edersiniz. Bunu düşünmen gerek.


1
Testi doğrulamak için harika bir nokta! Ayrıca: Bir ev inşa ederken, bir duvarı hareket ettirmek ZOR (ve bu izleri bırakır). Yazılımla, kodun etrafından dolaşmak nispeten kolaydır - istenmeyen değişiklikleri yakalamak için otomatik test yaptırmış olmanız koşuluyla.
Technophile

4

Birkaç TDD projesi yapana kadar bunu çok merak ederdim. Bunu yaparken başıma gelen çok özlü ve kapsamlı bir açıklama var:

Kod yazarken, kodun anlamlı bir şey yaptığından emin olmanın bir yolunu bulmanız gerekir. Yani kodunu test ediyorsun. Geçici test yapabilirsiniz. Ancak, bir şeyler yapmadan önce nasıl test edileceğini düşünüyorsanız, test yapmak daha iyi sonuç verir. Yani teste geçmeden önce test stratejisini tasarlarsınız.

Şimdi, test stratejinizi düşündüğünüzden beri, en azından bir parçası olarak otomatikleştirebilirsiniz, bir de TDD seviyesine sahip olduğunuza bakın. Testi geçene kadar kod yazmanız normaldir. Ne yaparsan yap, işe yarayana kadar kod yaz. Testleri patlatmak artık çok kolay.

Kapsam dışı nedenlerden dolayı her şeyi tek seferde yazmazsınız. Yani testleri bir kerede tasarlamıyorsunuz. Ama temelde olan bu. Sadece testin daha iyi planlanması, her zaman önünüzde test yazmazsınız. Bazen ilerledikçe daha fazlasını ekler ve daha önce tahmin etmediğiniz veya testi daha da sağlamlaştıracağınız hataları görürsünüz. Bazen kendinizi testler tasarlamadığınızı, elle test çalışmalarını da bulduğunuzdan emin olabilirsiniz.

Bu yüzden TDD, işinizi nasıl onayladığınızı görmek için çok uç bir yol.


4

Bu sorunun zaten kabul edilmiş bir cevabı olmasına rağmen, yazılı olmayan bir tasarım tarzından (bir test prosedürünün ardından "test ediciler tarafından manuel olarak gerçekleştirilen tüm testler) TDD'ye ekleyeceğim bir şey olduğuna inanıyorum. Bunlar benim kişisel gözlemlerim, yine de evrensel olduklarına inanıyorum.

Yeni bir şey yazarken, daha önce hiç yapmadığınız bir şeyi yazdığınızda, TDD ile TDD yapmama arasında önemli bir fark yoktur.

Genelde, bir fikri araştırmak için küçük bir kod parçası yazmak ve ardından "test" için bazı kodlanmış bitler eklemek ve ardından onu derlemek ve / veya yürütmek olur. İşe yararsa, kodlanmış öğeleri silin ve parametreleri, örnek değişkenleri vb. Ekleyerek kodu genelleştirin.

Bunu düşün. TDD ile aynı miktarda iş bu. Tek fark TDD'de "test etme" bitlerini ayrı bir dosyaya ayrı yazar ve sonunda silmemektir. TDD'de test kodunuzu saklarsınız .

Elbette, TDD'nin biraz daha organize olması, kodun test bitlerinin gerçek kodunuzdan nasıl ayrılacağını belirleyen biraz daha fazla çalışma olduğu anlamına gelir. Ancak daha önce birim testleri yazdıysanız, test kodunuzu nasıl modüler hale getireceğinizi öğreneceksiniz.


2

Neden test güdümlü geliştirme (TDD) ve geliştirme güdümlü test (DDT) hakkında çevik değil?

Sadece burada cıvıl cıvılyorum çünkü sorunun oldukça sakıncalı olduğunu düşündüğüm bir gerçeği ("çevik TDD ile ilgili" olduğunu) öne sürdüğünü düşünüyorum. Tüm cevaplar bu gerçeği verilmiş gibi kabul ediyor gibi görünüyor. Çevikliğin esas olarak TDD ile ilgili olduğunu varsayarlar (aka, birim düzeyinde test).

https://en.wikipedia.org/wiki/Agile_software_development#Agile_methods iyi bir düzine veya daha fazla farklı gelişim modelini listeler.

Özellikle düşünceye yönelik olarak davranış odaklı gelişim ve özellik odaklı gelişim sunabilirim. Tamamen farklı hayvanlar da temel TDD sunduğu tüm avantajlara yol ancak basit kırmızı-yeşil-refactor döngüsünden çok farklıydılar olabilir.

Yani benim cevabım ist:

  • "DDT" (diğer bir deyişle, uygulamanın ardından veya "üstünde" yazılı testler yapılması) gerçek yaşam nedenleriyle işe yaramaz; Zaman veya para baskısı alır almaz testler pencereden dışarı çıkar; IMO, sadece test yaptırmanın yararı için testler yapmak oldukça zor.
  • Çevik olarak, bu terimi temelde "tüm yapı taşları / sınıfları için birim testleri" (en azından Wikipedia'ya göre, durum testi) olarak adlandırıyorsanız, teste dayalı bir geliştirme (TDD) ile ilgili değildir . TDD çevik bir gelişme yapmanın sadece bir ihtimaldir.
  • Tam yığın yaklaşımı yapan BDD veya FDD gibi başka yöntemler de var. Senaryolarınızı hala önünüzde yazıyorsunuz, hala kırmızı-yeşil-yeniden düzenleyici bir döngünüz var ve hala senaryolarınız yeşil olana kadar uygulamaya devam ediyorsunuz, ancak tanımı gereği "testleriniz" (kullanıcı etkileşimi gibi davranarak) ve asla sadece bir tek ünite.

Tam BDD / FDD kapsama alanı olan bir uygulama ve tam ünite test kapsamı olan ve tam yığın testi olmayan bir ünite testi yapmamayı tercih ederim.

(TDD'nin, örneğin API'lerde elbette bir yeri var, ama burada konuştuğumuz şey bu değil.)

Yine, buradaki diğer tüm cevapları küçümsemeye çalışmıyorum, sadece sorunun oldukça dar formüle edildiğine ve alanın sunabileceği çok şey olduğuna dikkat çekiyorum.


Bir başkasını biliyordum ama bu yazıyı yazarken daha mantıklı görünüyordu. TDD'nin neden API için daha iyi olduğu konusunda ayrıntılı bilgi vermek ister misiniz? MVC'li bir web istemcisinin farklı olduğunu söylemek nasıl olurdu?
nerdlyist,

1
API'lerde çok detaylı bir sözleşmeyi takip etmeleri son derece önemlidir ; Her yöntem çağrısı, kullanıcıların (diğer programlar olduğu) doğru kullanabilmesi için çok öngörülebilir davranmalıdır. Bu, ünite testlerinin gerçekten parladığı yerdir. OTOH, bir uygulamada, insan kullanıcılarınızın amaçlandığı gibi çalışması için ihtiyaç duyduğu özellikler için çok önemlidir. Elbette, "dahili" inizin de doğru olması daha iyidir, ancak her bir metodu test etmek yerine (örneğin, kullanıcı arayüzünden DB'ye ve geriye doğru) işlevselliği için "uçtan uca" iyi bir kapsama sahip olmak daha önemlidir. insan son kullanıcılar zaten görmeyecek).
AnoE

Tabii ki, hepsi burada farklı derecelerde - bir yerde çok karmaşık yöntemlere / sınıflara sahip olmanız gerekiyorsa, burada birim testlerde saçma olması mantıklı olabilir (örneğin: jeokoordinatlar arasındaki mesafeleri hesaplama); ancak toplu iş (örneğin, iş uygulamalarında) genel iş akışıdır.
AnoE

0

Sık sık bu şekilde yazıldığını görmemenize rağmen, çevikliğin arkasındaki mantıklı düşüncenin çoğu, kodu yeniden yazmanın ilk defa iyi yazmaktan daha iyidir. Her kodu tekrar yazdığınızda kodu geliştirir ve kendinizi geliştirirsiniz. İlk defa "Doğru" almak, daha yavaş ve daha kırılgan olma eğilimindedir.

Ev benzetmesi o kadar da kötü değil, ama ne kadar süredir ev yapımı hakkında bildiğimizi ve yazılım mühendisliği hakkında ne kadar uzun süredir bildiğimizi düşünmelisiniz - ayrıca yazılım mühendisliğinin karmaşıklığı uzun bir köprü kurmaya daha yakın veya bir evden 20 katlı kule. Yeni diller ve araçlar kuruldukça, binayı tamamen farklı şekil, boyut ve malzemelerle inşa etmek isteyen her inşaatçı gibi yapmalıyız. Kaos tamamlayın.

Ancak, inceleme, kod sınaması için iyi bir benzetme değildir. Yazılımda, müfettişlerimizin iyi olduğu noktalara bile değiliz (Çeşitli beceri seviyelerindeki meslektaşlarınız hariç). Ayrıca, belki de çoğunlukla rasgele bazı "kodlama standartları" dışında (boyasının ve çim düzeninizin yapıdan daha çok test edilmesi gibi) dışında denetlemek için düzenlemelerimiz yoktur.

Test-ilk, daha çok bir duvar inşa ettiğinize benziyor, sonra kaldırmadan ve evinize yerleştirmeden önce dengeyi sağlamak için üzerine biraz baskı uyguladınız. Yerleştirmeyi denemeden önce bıraktığınız deliğe oturduğundan emin olmak için pencereyi ölçmek gibidir.

Asırlarca önceki mimarlık bilgimiz, kalıplarımız, yönetmeliklerimiz ve matematiğimiz olmadan şu anda köprülerimizin çalışacağını ispat etmemizi gerektirecek bir dizi köprü kurmak zorundaysanız, köprülerinizi bir LOT test ediyor ve yeniden inşa ediyor olursunuz.

Sonunda analoji olmayan bir nokta - her zaman kodunuzun bir bölümünü yeniden yazmanıza izin verilen bir yazılımla hem kodunuzu hem de becerinizi önemli ölçüde geliştirirsiniz. Kodu tekrar yazmak için her şansınızı kullanın. TDD harika bir bahane olabilir.

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.