TDD neden çalışıyor? [kapalı]


92

Test odaklı geliştirme (TDD) bugünlerde büyük. Programmers SE'de ve diğer mekanlarda çok çeşitli sorunlara çözüm olarak önerildiğini sık sık görüyorum. Neden işe yaradığını merak ediyorum.

Mühendislik açısından bakıldığında, iki nedenden dolayı beni şaşırtıyor:

  1. "Geçti kadar test testi + refactor" yaklaşımı inanılmaz anti-mühendislik görünüyor. Eğer inşaat mühendisleri bu yaklaşımı köprü inşaatı için ya da araba tasarımcıları arabaları için kullanmışlarsa, örneğin köprülerini ya da arabalarını çok yüksek maliyetlerle yeniden şekillendireceklerdi ve sonuç iyi düşünülmüş bir mimariye sahip olmayan bir karmaşa olurdu. . "Başarılı geçene kadar refactor" kılavuzu genellikle mimari tasarımı unutmak ve teste uymak için ne gerekiyorsa yapmak için bir zorunluluktur ; Başka bir deyişle, kullanıcı yerine test, gereksinimi belirler. Bu durumda, sonuçlarda iyi "kayıpları" nasıl garanti edebiliriz, yani sadece doğru değil aynı zamanda genişletilebilir, sağlam, kullanımı kolay, güvenilir, güvenli, güvenli vb. Mimarlığın genelde yaptığı şey budur.
  2. Test, bir sistemin çalışmasını garanti edemez; sadece olmadığını gösterebilir. Başka bir deyişle, test size bir sistemin bir testi geçememesi durumunda kusur içerdiğini gösterebilir, ancak tüm testleri geçen bir sistem onları geçemeyen bir sistemden daha güvenli değildir. Test kapsamı, test kalitesi ve diğer faktörler burada çok önemlidir. “Tüm yeşil” sonuçların birçok insana ürettiği sahte güvenli duygular sivil ve havacılık endüstrilerinde son derece tehlikeli olarak rapor edilmiştir, çünkü “sistem iyi” anlamına geldiğinde “sistem iyi” olarak yorumlanabilir. test stratejimiz olarak ". Genellikle, test stratejisi kontrol edilmez. Veya testleri kim test ediyor?

Özetle, TDD'de "sürülen" bit ile "test" bitinden daha fazla endişeliyim. Testler mükemmel; Anlamadığım, tasarımı yaparak onu sürmek.

Yazılım mühendisliğinde TDD'nin neden iyi bir pratik olduğu ve yukarıda açıkladığım konuların yazılım için neden alakasız olduğunu (veya yeterince alakalı olmadığını) içeren cevapları görmek istiyorum. Teşekkür ederim.


53
Köprüler, arabalar ve diğer fiziksel tasarımlar, yazılım kadar dövülebilir değildir. Bu önemli bir ayrımdır ve yazılım ile gerçek mühendislik arasındaki karşılaştırmaların her zaman alakalı olmadığı anlamına gelir. Köprüler için işe yarayan şey yazılım için çalışmayabilir ve bunun tersi de geçerlidir.
Lars Wirzenius

9
Biraz şüphenle aynı fikirdeyim. Mesela itiraf etmeliyim ki, bir test odasına sahip olmanın, kod yazarken bir şekilde "yumuşatılmış" bir dikkatin yan etkisi olabileceği izlenimini edindim. Tabii (eğer refactor olanağına sahip olmak istiyorsanız zorunlu bir) testler iyi bir şey, ancak yalnızca ek ayrıntılar, sınır durumlarda, verimlilik veya genişletilebilirlik dikkat ve onlar bunu değiştirmez eğer.
6502

2
@ 6502: Elbette! TDD gümüş bir mermi değildir ve yazılım geliştirme sırasında ortaya çıkan tüm sorunları çözmez. Bununla birlikte, iş akışını düzenlemek için kullanışlı bir yöntemdir. Örneğin, tüm sınır davalarının testlerle kapsanması şartı getirebilirsiniz. Bu sınır davalarının ne olduğunu hala bilmeniz gerekiyor, ancak şimdi kodunuzun onlarla doğru bir şekilde ilgilenip ilgilenmediğini kontrol etmek için bir aracınız da var.
Milch

2
@CesarGon, bir süre önce SO'da sorduğum bu soruda da ilginç olabilir ... Oldukça TDD değil, ilgili ... Bazı çok aydınlatıcı cevaplar var.
AviD

6
Bir inşaat mühendisliği / yazılım geliştirme analogunun dayanamaması ne kadar şaşırtıcı. Aynı çizgiler boyunca, çimlerimi biçtiğim gibi krep pişiremediğimi de fark ettim.

Yanıtlar:


66

Burada bir yanlış anlaşılma olduğunu düşünüyorum. Yazılım tasarımında, tasarım ürüne çok yakındır. İnşaat mühendisliği, mimarlıkta, tasarım asıl üründen ayrıştırılır: tasarıma sahip, daha sonra bitmiş ürüne dönüştürülmüş planlar vardır ve bunlar büyük miktarda zaman ve çaba ile ayrılır.

TDD tasarımı test ediyor. Ancak her otomobil tasarımı ve bina tasarımı da test edilmiştir. İnşaat teknikleri önce hesaplanır, daha sonra daha küçük ölçekte test edilir, daha sonra gerçek bir binaya yerleştirilmeden önce daha büyük ölçekte test edilir. Örneğin, H-kirişlerini ve yükü icat ettikleri zaman, bununla birlikte ilk köprüyü inşa ettikleri zaman, bunun denenip yeniden denendiğinden emin olun.

Araba tasarımları da prototip tasarlayarak test edilir ve evet, kesinlikle beklentileri karşılayana kadar kesinlikle doğru olmayan şeyleri ayarlayarak. Bu sürecin bir kısmı daha yavaştır, çünkü dediğiniz gibi, ürünle uğraşamazsınız. Ancak, bir otomobilin her yeniden tasarımı, eskilerinden öğrenilen deneyimlerden yararlanır ve her binanın arkasındaki alan, ışık, yalıtım, güç vb. ve yeni olanlar için yeniden tasarlandı.

Ayrıca, parçalar test edilmiştir. Belki de yazılımla tam olarak aynı tarzda değil, ancak mekanik parçalar (tekerlekler, ateşleyiciler, kablolar) genellikle ölçülmekte ve boyutların doğru olduğunu, hiçbir anormallik görülmeyeceğini, vb. Olduğunu bilmek için strese maruz bırakılmaktadır. ölçülürler, kırılmış olanları bulmak için tuğlaları vururlar, aslında bazı yapılandırmalarda veya başka bir testte test edilebilirler veya gerçekten teste koymak için büyük bir grubun sınırlı bir temsilini çizerler.

Bunlar TDD ile yerine koyabileceğiniz şeyler.

Ve gerçekten de, test garanti değildir. Programlar çöküyor, arabalar yıkılıyor ve rüzgar estiğinde binalar komik şeyler yapmaya başlıyor. Ama ... 'güvenlik' bir boole meselesi değildir. Her şeyi dahil edemediğiniz zaman bile, örtbas edebilme - demek ki - olayların% 99'u yalnızca% 50'sinden daha iyidir. Test etmemek ve daha sonra çeliğin iyi bir şekilde yerleşmediğini bulmak ve kırılgandır ve ana yapınızı yeni yerleştirdiğinizde bir çekiçin ilk çırpısında kırılır ve para harcamak zordur. Binaya hala zarar verebilecek başka endişelerin var olması, kolayca önlenebilir bir hatanın tasarımınızı azaltmasına izin vermeyi daha az aptallaştırmaz.

TDD uygulamasına gelince, bu bir dengeleme meselesidir. Bunu bir şekilde yapmanın maliyeti (örneğin, test etme ve daha sonra parçaları toplama), başka bir şekilde yapmanın maliyeti. Her zaman bir dengedir. Ancak, diğer tasarım süreçlerinin yerinde test ve TDD olmadığını düşünmeyin.


7
İmalatta testlerin nerede gerçekleştiği hakkında konuşmak için +1. Harika nokta.
Adam Lear

11
"Parçalar test edildi" diyorsunuz. Tabii, ancak test odaklı tasarlanmadı. Bir uçak parçası, test odaklı bir şekilde değil, mimari ve büyük bir tasarımla ön planda tutularak tasarlanmıştır. TDD ile benzerlikler burada yoktur.
CesarGon

3
Buna ek olarak: TDD, bence temel olarak, sonunda büyük bir "hepsi ya da hiçbir şey" yerine parçaları kontrol edebildiğinizden emin olmanın yolları hakkında. Ancak TDD'nin adagium, 'ilk önce bir test yapın', 'ne yapmak istediğinizi düşünmeden önce bir test yapması' anlamına gelmez. Çünkü bir testi düşünmek tasarımın bir parçasıdır. Tam olarak ne yapmasını istediğinizi belirtmek, tasarlamaktır. Daha önce yazmaya başlamadan önce bazı tasarımları zaten yaptınız. (Bu şekilde 'teste dayalı tasarım' teriminin yanıltıcı bir şekilde gerçekten bir geri besleme döngüsü olduğu yoldaki yolu ima ettiğini düşünüyorum).
Inca

2
+1: Yazılım tamamen tasarımdır. Söz konusu köprü benzetmesi tamamen yanlıştır. TDD tamamen dış ünite testi için geçerlidir. Test Odaklı Tasarım, tüm tasarım katmanlarında uygulanır.
S.Lott

3
@CesarGon: Hayır, TDD GELİŞTİRMEYİ test ederek sürüyor . Bu, tasarımı sürmekten farklı. Tasarım, sistemi nasıl kullanacağınızı ve bu davranışı tekrarlamak için hangi testleri uygulamanız gerektiğini belirler. Bu testleri uygulamak çoğu zaman tasarımı geliştirmenize yardımcı olur .
deworde

26

IMO, TDD'nin başarı hikayelerinin çoğu sahte ve sadece pazarlama amaçlı. Bununla çok az başarı olabilir, ancak sadece küçük uygulamalar için. TDD ilkelerinin kullanıldığı büyük bir silverlight uygulaması üzerinde çalışıyorum. Uygulamada yüzlerce test var, ancak yine de kararlı değil. Uygulamanın bazı bölümleri, karmaşık kullanıcı etkileşimleri nedeniyle test edilemez. Çok fazla alay ve kodun anlaşılması zor olan test sonuçları.

Başlangıçta TDD'yi denediğimizde, her şey iyi görünüyor. Çok sayıda test yazabildim ve birim testi için zor olan parçaları alay ettim. Makul miktarda bir kodunuz olduğunda ve bir arayüz değişikliği yapmanız gerektiğinde, sizin uyarınız. Pek çok testin düzeltilmesi gerekiyor ve koddaki gerçek değişiklikten daha fazla testi yeniden yazacaksınız.

Peter Norvig, Coders At Work kitabında TDD hakkındaki görüşünü açıklıyor.

Seibel: Peki ya tasarımı geliştirmek için test kullanma fikri ne olacak?

Norvig: Testleri daha çok bir tasarım yolu değil hataları düzeltmenin bir yolu olarak görüyorum. “Yaptığın ilk şey, sonunda doğru cevabı aldığımı söyleyen bir test yazmak” demenin bu aşırı yaklaşımı ve sonra onu çalıştırıyor ve başarısız olduğunu görüyorsun ve sonra, “Ne yapıyorum? sıradaki ihtiyacınız var mı? ”- bu bana bir şey tasarlamanın doğru yolu gibi görünmüyor. Çözümün önceden belirlenmiş olması çok basit olsaydı, mantıklı olur gibi görünüyor. Bence önce düşünmelisin. “Parçalar neler? Bazılarının ne olduğunu öğrenene kadar parçalar için nasıl test yazabilirim? ”Ve sonra, bunu yaptıktan sonra, bu parçaların her biri için testler yapmak ve birbirleriyle nasıl etkileşime girdiklerini iyi anlamak disiplindir. ve sınır davaları vb. Hepsinde testler olmalı. Ancak, tüm tasarımı “Bu test başarısız oldu” diyerek sürdüğünüzü sanmıyorum.


7
Şimdi, eğer bu gerçekleri TDD milletine ve danışmanlarına söylerseniz, alacağınız cevap şu olacaktır:well, you haven't done TDD right!
Navaneeth KN

10
Ve haklılardı. Çok yüksek hacimli bir sistemde BDD / TDD yapıyoruz ve iyi çalışıyor. Testler size beklenen davranışı çiğnediğinizi söylemek için var. Eğer bunu daha sonra gidip değiştiriyorsanız testleri “kırmak”, aslında yanlış yapıyorsunuz demektir. Testler önce sistemin YENİ davranışını sağlamlaştırmak için değiştirilmeli, sonra siz onu değiştirmelisiniz. Ve evet, doğru yapıyorsanız, testlerinizi "bu şeyin ne yapması gerekiyor?" İle başlayarak yazarsınız ve sınama yazma işlemi “BT'nin işini yapması için neye ihtiyacı olduğunu” düşünmenize yardımcı olur. Oh, ve hiçbir danışman kullanılmadı ...
Andy

4
Çok fazla test yapmak, uygun bir tasarım oluşturmanıza engel olmaz. Etrafında kaç test yapıldığına bakılmaksızın, yüksek derecede eşleşmiş bir tasarım, her zaman kırılgan olacaktır. Bu tasarıma testleri yerleştirmek her şeyi çok daha kötü hale getirebilir.
Newtopian

3
Yanlış yapmak ya da çok eşleşmiş bir tasarım olmak meselesi değil. Gerçek şu ki arayüzler değişiyor. Bu, bu arayüzü kullanan tüm testlerin değişmesi gerektiği anlamına gelir. Büyük sistemlerde, testleri gerekli değişikliklerle senkronize tutmak, uygulamanın zorlanmasına başlayabilir. Arayüz değişikliklerinin olasılığı daha fazla olduğundan, çevik bir gelişme gerçekleştiriyorsanız, bu daha da büyük bir problem haline gelir. Metodolojilerin çalışmadığı durumlarda metodolojinin savunucuları, yanlış yaptığınız konusunda ısrar ediyorlar. Metodolojinin tüm problem alanları için uygun olmaması daha olasıdır.
Dunk

2
Tecrübelerime göre TDD küçük uygulamalar veya modüller için çalışıyor. Karmaşık bir şey üzerinde çalışmak zorunda kaldığımda TDD beni yavaşlatıyor, çünkü aklımdaki genel resmi netleştirmeden önce detaylı (çalıştırılabilir) bir özellik yazmaya zorluyor; Belirli derslere ihtiyaç duymadığımı öğrenirsem bir sürü testten vazgeç (hala tasarımla oynuyorum). Bu gibi durumlarda önce makul bir genel tasarıma sahip olmayı ve ardından uygulama detaylarını (muhtemelen TDD kullanarak) seçmeyi tercih ederim.
Giorgio

25

Test Odaklı Tasarım aşağıdaki nedenlerden dolayı benim için çalışıyor:

Belirtimin uygulanabilir bir şeklidir.

Bu, test durumlarından görebileceğiniz anlamına gelir:

  1. BU kodun tamamı, test sonuçlarında tam da beklenen sonuçlar olduğu için şartnameyi yerine getiriyor. Gözle muayene (test vakalarının geçmesini bekler) derhal "ah, bu test, bu durumda verilen faturayı çağırmanın bu sonucun olması gerektiğini kontrol eder" diyebilir.
  2. NASIL kod çağrılmalıdır. Testleri yapmak için gereken gerçek adımlar, herhangi bir dış iskele olmadan doğrudan belirlenir (veritabanları alay edilir vb.).

Görünümü önce dışardan yazıyorsun.

Sık sık kod, sorunu ilk önce çözeceğiniz bir şekilde yazılır ve ardından yeni yazdığınız kodun nasıl çağrılacağını düşünürsünüz. Bu sık sık garip bir arayüz sağlar çünkü sık sık "sadece bir bayrak ekler" vb. Daha kolaydır. "Bunu yapmak için test etmemiz gerekir." Bu, kodun aksi yönde değil, arama arayüzüne göre yazılacağı için daha iyi modülerlik sağlayacaktır.

Bu genellikle daha az açıklayıcı belgeler gerektiren daha temiz kodla sonuçlanacaktır.

Daha hızlı bitirdin

Çalıştırılabilir formda belirtime sahip olduğunuzdan, tam test paketi geçtiğinde yapılır. İşleri daha ayrıntılı bir düzeyde netleştirirken daha fazla test ekleyebilirsiniz, ancak temel ilke olarak, ilerleme ve işin ne zaman bitmiş olduğu konusunda çok net ve görünür bir gösterge elde edersiniz.

Bu, çalışmanızın ne zaman gerekli olduğunu ya da gerekmediğini söyleyebileceğiniz anlamına gelir (bir testi geçmek için yardımcı olur), daha azını yapmanız gerekir.

Üzerinde düşünmek olanlar için onlar için faydalı olabilir, bir sonraki kütüphane rutininiz için TDD'yi kullanmanızı tavsiye ederim. Yavaşça çalıştırılabilir bir teknik özellik belirleyin ve kodun testleri geçmesini sağlayın. Tamamlandığında, çalıştırılabilir özellik kitaplığın nasıl çağrılacağını görmesi gereken herkes tarafından kullanılabilir.

Son Çalışma

“Örnek olay incelemelerinin sonuçları, dört ürünün ön salım öncesi kusur yoğunluğunun TDD uygulamasını kullanmayan benzer projelere göre% 40 ile% 90 arasında düştüğünü göstermektedir. TDD'yi kabul ettikten sonra ilk gelişme zamanı. " ~ 4 Endüstriyel Ekip'in Sonuçları ve Deneyimleri


5
Buna, işiniz bittiğinde hakkında gerçekten makul ve net bir kılavuza sahip olduğunuzu da eklerdim. Eldeki görevi tamamladığınızı nesnel olarak doğrulamak için bazı net prosedürler olmadan, bunu bilmek zordur. Kendi deneyimim, bir görevin tamamlanıp tamamlanmadığını ve hattın sürekli ve sürekli hareket etmesini "müzakere etmek" ile çok fazla saat ve günü harcıyor. Bu, zamanlama da dahil olmak üzere tüm proje yönetimi seviyelerini etkiler, çünkü böyle bir görevi nasıl planlayabilirsiniz? Daha hızlı geri dönüşlü daha net hedefler verimi ve iletişimi arttırır.
Edward Strange

Bu kabul edilen cevap olmalı.
Niing

19

Yazılım oluşturma işlemi, kodu yazma işlemi değildir. Hiçbir yazılım projesi önce 'geniş kapsamlı' bir plan olmadan başlamaz. Tıpkı bir nehrin iki yakasını köprüleme projesi gibi, önce böyle bir plana ihtiyaç var.

TDD yaklaşımı (çoğunlukla) birim testi ile ilgilidir - en azından insanlar böyle düşünmeye meyillidir - bu, yazılım kodunun en düşük seviyeli bitlerini yaratır. Tüm özellikler ve davranışlar önceden tanımlanmışsa ve aslında ne elde etmek istediğimizi biliyoruz.

Yapısal mühendislikte biraz şuna benziyor:

“Bu iki metal parçasını birbirine bağladık ve bağlantının kesme kuvvetlerini x sırasına göre sürdürmesi gerekiyor. Bunu yapmak için hangi bağlantı yönteminin en iyisi olduğunu test edelim '

Yazılımın bir bütün olarak çalışıp çalışmadığını test etmek için kullanılabilirlik testleri, entegrasyon testleri ve kabul testleri gibi başka tür testler tasarlarız. Bunlar da kod yazmaya başlamadan önce yapılan çalışmadan önce tanımlanmalı ve ünite testleri yeşil olduğunda gerçekleştirilmelidir.

V-Modeline bakınız: http://en.wikipedia.org/wiki/V-Model_%28software_development%29

Bir köprü için nasıl çalışacağını görelim:

  1. Yerel bir hükümet köprü inşa eden bir şirkete şunları söylüyor: “Bu iki noktayı birbirine bağlamak için bir köprüye ihtiyacımız var. Köprünün saatte n trafik miktarına izin vermesi ve 21 Aralık 2012 için hazır olması gerekiyor” - bu bir tanımdır. Kabul testi: Bu testi geçemezlerse, şirket tam olarak (veya herhangi bir) para alamaz.

  2. Şirket yönetimi proje programına karar verir. Çalışma ekipleri kurdular ve her ekip için hedefler belirlediler. Takımlar bu hedeflere ulaşmazsa - köprü zamanında inşa edilmeyecektir. Ancak - burada bir miktar esneklik var. Ekiplerden birinin bazı problemleri varsa, şirket, gereklilikleri değiştirerek, taşeronları değiştirerek, daha fazla kişiyi işe alarak vb. Yaparak, tüm projenin hala 1. maddede belirtilen hedefi yerine getirmesini sağlayabilir.

  3. Yukarıda verdiğim örnekte olduğu gibi belirli köprü bileşenlerini tasarlamaktan sorumlu bir ekip içinde. Bazen çözüm açıktır, çünkü köprü kurmaya ilişkin geniş bir bilgi birikimimiz vardır (yazılım geliştirmede iyi test edilmiş bir kütüphane kullanmak gibi - bunun sadece reklamı yapıldığını kabul edersiniz). Bazen birkaç tasarım oluşturmanız ve en iyisini seçmek için bunları test etmeniz gerekir. Yine de, bileşenin üzerinde test edildiği kriterler önceden bilinir.


Sizi doğru anlarsam, TDD'nin (a) yalnızca birim test için kullanıldığı ve (b) diğer test yaklaşımlarının da eşlik ettiği sürece tamam olduğunu söylüyorsunuz. Bu durumda, OP'deki 2 numaralı noktaya hitap edebilir. 1 numaralı noktaya nasıl hitap edersiniz?
CesarGon

@CesarGon: TDD, entegrasyon testleri için de harika çalışıyor.
sevenseacat

Nokta 1, bir otomobil veya köprü için yapılan son projenin kabul edilmesinden önce, tüm ayrıntılarının gözden geçirildiği ve 'geniş kapsam planı' tarafından öngörülen şartlara göre test edildiği birçok tekrardan geçtiği için harekete geçiyor . Çoğunlukla kağıda (ya da bilgisayar belleğinde) yapılır, çünkü bu durumda daha ucuzdur, ancak her iki yapının (belki de köprü durumunda değil) bileşenlerinin yanı sıra genellikle fiziksel prototipler oluşturduğuna dikkat edin.
Millet

@Karpie: Ayrıca kabul testleri için! Çalışmanızın müşteri tarafından kabul edilmesi için neyin gerekli olduğunu önceden bilmeniz gerekir.
Millet

1
Tamam ozaman. Çalışmaya başlayan ilk ekip, müşterilerin kriterlerini karşılayabilecek bir köprü tasarlaması, aynı zamanda ucuz ve muhtemelen iyi görünmesi ve rüzgârın ilk kuvvetinde aşağı inmemesi söylenen bir mimar ekibidir. Ekip bu kriterleri karşılayan az çok kaba tasarım önerebilir, daha sonra daha az detaylı bir tasarım yapabilir, daha sonra bir tanesini seçip daha detaylı çalışabilir, tekrar edebilir, tekrarlayabilir, tasarım hazır olana kadar tekrar edebilir (yani verilen kriterleri karşılayacak ve yeterince ayrıntılı olacak şekilde projenin bir başka aşaması başlayabilir)
Mchl

18

Aklımda TDD çalışıyor çünkü

  • Uygulamaya karar vermeden önce birimin ne yapmasını istediğinizi tanımlamanızı zorunlu kılar.
  • Kodunuzu doğal olarak yeniden kullanılabilir hale getirir, çünkü hem testlerde hem de üretim senaryolarında kullanmanız gerekir.
  • Daha iyi tasarımlara yönelme eğiliminde olan parçaları test etmek için daha küçük bir hevesle kod yazmanızı teşvik eder

Özellikle yükseltdiğiniz noktalarda

  • Kod tuğla veya çelikten daha kolay anlaşılır olduğundan değişiklik yapılması daha ucuzdur. Davranışın değişmemesini sağlamak için testleriniz varsa hala ucuzdur
  • TDD tasarım yapmamak için bir mazeret değildir - yüksek seviyede bir mimarlık hala tavsiye edilmektedir, sadece çok fazla ayrıntı içermemektedir. Big Up Front Design'ın cesareti kırılıyor, ancak yeterince tasarım yapılması teşvik ediliyor
  • TDD bir sistemin çalışmasını garanti edemez, ancak bunun dışında kaçıracak çok sayıda küçük hata meydana gelmesini önler. Ayrıca, genellikle daha iyi faktoring kodunu teşvik ettiğinden, sık sık daha az tehlikeli olması daha kolay anlaşılır

3
Ayrıca, kusurlar keşfedildiğinde, başka bir test ekleyeceğinizde tekrar edilmeyeceklerinden emin olabileceğinizi de eklemelisiniz.
Andy

16

TL; DR

Programlama hala bir tasarım etkinliğidir, inşaat değildir. Birim testleri yazdıktan sonra, kodun yaptığı şeyi yaptığını, yararlı bir şey yapmadığını doğruladığını doğrular. Test başarısızlıkları gerçek değerdir çünkü hataları erken yakalamanıza izin verir.

Kod Tasarımdır

PPP'nin 7. Bölümünde "Bob Amca" bu konuda doğrudan konuşuyor. Bölümün çok başında, Jack Reeves'in, kodun tasarım olduğunu önerdiği mükemmel bir makalesine atıfta bulunuyor (bağlantı, konuyla ilgili üç makalesinin tümünü toplayan bir sayfaya gider).

Bu argümanın ilginç yanı, inşaatın çok pahalı bir faaliyet olduğu diğer mühendislik disiplinlerinden farklı olarak, yazılımın yapımının nispeten ücretsiz olduğunu (IDE'nizde derleme yapın ve sizin kendi yazılımınızı oluşturuyorsunuz). Yazma kodunu bir inşaat faaliyeti yerine tasarım faaliyeti olarak görürseniz, kırmızı-yeşil-refactor çevrimi temel olarak tasarımda bir alıştırmadır. Tasarımınız siz testler yazdıkça, onları tatmin edecek kod ve yeni kodu mevcut sisteme entegre etmek için yeniden düzenlenir.

Şartname olarak TDD

TDD için yazdığınız birim testleri, onları anladığınız gibi doğrudan belirtimin çevirisidir. Spesifikasyonunuzu en az şekilde karşılayan bir kod yazarak (testlerinizin yeşile dönmesini sağlar), yazdığınız tüm kodlar belirli bir amaç için oradadır. Bu amacın karşılanıp karşılanmadığı tekrarlanabilir bir test ile doğrulanır.

İşlevselliğe Testler Yaz

Kod testinden sonra testleri yazdığınızda, birim testlerinde sık karşılaşılan bir hata meydana gelir, kodun yaptığı şeyi test etmesi ile sonuçlanır. Başka bir deyişle, bunun gibi testleri göreceksiniz

public class PersonTest:Test
{
   [Test]
   TestNameProperty()
   {
      var person=new Person();
      person.Name="John Doe";
      Assert.AreEqual("John Doe", person.Name);
   }
}

Sanırım bu kod faydalı olabilir (birisinin basit bir özellik ile müstehcen bir şey yapmadığından emin olun). Bir spesifikasyonu doğrulamaya hizmet etmez. Ve dediğiniz gibi, bu tür testlerin yazılması sizi yalnızca şimdiye kadar götürür.

Yeşil İyiyken Değer Kırmızıda Yatıyor Beklenmeyen bir test hatası aldığımda TDD'de ilk gerçek "aha" anımı yaşadım. Yaptığım bir çerçeve için yaptığım testler vardı. Yeni bir özellik ekleyerek, bunun için bir test yazdım. Sonra testi geçmek için kodu yazdı. Derle, test et ... yeni testte yeşil renk var. Ama kırmızıya dönmeyi beklemediğim bir testte kırmızı çıktı.

Başarısızlığa baktığımda, rahat bir nefes alıyorum, çünkü o böceği bir süredir test edemediğimden bu böceği yakalayacağımı sanmıştım. Ve olması çok çirkin bir hataydı. Neyse ki, test yaptım ve bana hatayı düzeltmek için ne yapmam gerektiğini tam olarak söyledi. Test olmadan, sistemimi oluşturmaya devam edecektim (o koda bağlı diğer modülleri etkileyen böcek ile) ve hatanın keşfedilmesiyle birlikte, hatayı doğru şekilde düzeltmek büyük bir görev olurdu.

TDD'nin asıl yararı, dikkatsiz terkedilme ile değişiklik yapmamıza izin vermesidir. Programlama için bir güvenlik ağı gibi. Bir trapez sanatçısı bir hata yapar ve düşerse ne olacağını bir düşün. Net, bu şaşırtıcı bir hata. Olmadan, bu bir trajedi. Aynı şekilde, TDD sizi kemik kafalı hataları proje öldürme felaketlerine dönüştürmekten kurtarıyor.


4
Kırmızı testleri yakalama hatalarının değeri, özellikle TDD'ye değil, Genel olarak Birim Testinin bir niteliğidir.
Robert Harvey,

2
Bu noktada haklısın. Ancak, post-hoc birim testleriyle ilgili belirli bir hatanın meydana gelme olasılığı düşüktür.
Michael Brown,

1
Bu iddiayı bazı kanıtlarla, verilerle veya somut analizlerle destekleyebilir misiniz?
CesarGon

1
@CesarGon bu çalışma , küçük bir projede çalışan programcılar iken, TDD kullanan geliştiricilerin, testten sonra (% 92-98% vs% 80-90) test sonuçlarına göre daha iyi test kapsamına sahip olduklarını ve sonuçta daha fazlasını yakaladıklarını ileri sürmektedir. gelişim sırasındaki kusurlar (TDD kullanılarak üretilen kodda bulunan hataların% 18 daha az).
Jules

11

Teste Dayalı Gelişimi savunan, hatta Teste Dayalı Tasarımı (farklı olan) test eden uygulamaları kanıtlayan bir kişi bulamazsınız . Öyleyse şuna saman adam diyip bitirelim.

Testlerin zaman ve çaba kaybı olduğunu söyleyen TDD'den hoşlanmayan veya etkilenmeyen hiç kimseyi bulamazsınız. Testler uygulamaları ispatlamamasına rağmen, hataları bulmada oldukça faydalıdır.

Bu iki şey söylendiğinde, iki taraf da yazılım üzerinde testler yapmak konusunda farklı bir şey yapmıyor. Her ikisi de test yapıyor. Her ikisi de mümkün olduğu kadar çok hata bulmak için testler konusunda RELY ve her ikisi de bir yazılım programının çalıştığını ve aynı zamanda keşfedildiğini doğrulamak için testleri kullanır. Yarısı ipucu olan hiç kimse test etmeden yazılım satmaz ve yarısı ipucu olan hiç kimse testin tamamen hatasız sattığı kodu vermesini beklemez.

Bu nedenle, TDD ile TDD olmayan arasındaki fark testlerin yapılması değildir. Fark, testlerin yazıldığı zamandır. TDD testlerinde yazılım ÖNCE yazılır. TDD'de olmayan testler yazılım ile uyumlu olarak veya sonrasında yazılır.

İkincisi ile ilgili gördüğüm mesele, testin daha sonra yazılan yazılımı istenen sonuçtan veya şartnameden daha fazla yazmayı hedefleme eğiliminde olmasıdır. Test ekibinin geliştirme ekibinden ayrı olmasına rağmen, test ekibi yazılıma bakma, onunla oynama ve onu hedefleyen testler yazma eğilimindedir.

Projenin başarısını okuyanlar tarafından zaman ve tekrar fark edilen bir şey, müşterinin istediklerini ne sıklıkta düzenleyeceği, gelişim çalışanlarının kaçtıkları ve bir şeyler yazdıkları ve müşteriye "yapıldığını" söyleyerek geri döndükleri zamanlar. Müşterinin istediği şeyi tamamen ve tamamen DEĞİLDİR. "Ama bütün sınavlardan geçiyor ..."

TDD'nin amacı bu "dairesel argümanı" kırmak ve yazılımın kendisi olmayan yazılımı test eden testler için temel sağlamaktır. Testler "müşterinin" istediği davranışı hedeflemek için yazılmıştır. Yazılım daha sonra bu testleri geçmek için yazılır.

TDD bu sorunu çözmek için çözümün bir parçası . Bu attığın tek adım değil. Yapmanız gereken diğer şeyler daha fazla müşteri geri bildirimi olduğundan ve daha sık olduğundan emin olmaktır.

Tecrübelerime göre TDD başarılı bir şekilde uygulanması çok zor bir şey. Ürün olmadan önce test yapmak zor, çünkü çok sayıda otomatik test, otomasyon yazılımının doğru şekilde çalışabilmesi için bir şeyler yapmayı gerektirir. Ayrıca, ünite testine alışkın olmayan geliştiricilerin bunu yapması zor. Zaman ve tekrar tekrar ekibimdeki insanlara testleri İLK yazmasını söyledim. Aslında bunu yapacak birini almadım. Sonunda, zaman kısıtlamaları ve politika tüm çabaları mahvetti, böylece artık birim testleri bile yapmıyoruz. Elbette, bu kaçınılmaz olarak, tasarımın yanlışlıkla ve ciddi bir şekilde birleştiğine yol açıyor, böylece istemesek bile, şimdi uygulamanın yasaklanması pahalı olacaktı. Bunu önlemek, TDD'nin en sonunda geliştiricilere sağladığı şeydir.


+1 Kapsamlı cevap için teşekkürler, Noah. TDD ile TDD olmayan arasındaki en büyük farkın testlerin yazıldığı tarihte olduğunu kabul ediyorum. Ancak, ben de TDD ilk "D" TDD'deki, bütün gelişme olduğunu, yani "tahrik" anlamına gelir düşünüyorum tahrik testi ile. En şaşırtıcı bulduğum şey bu. Test edilecekleri yazmadan önce, test edilecekleri kurgulamıyorum. Fakat testlerin sürmesine izin vermek? Yüzeysel (yani sonuç) iyi olduğu sürece yeşil ışıktan ne kadar farklı olabilir ki?
CesarGon

Cesar, bir geliştirme görevinin ne zaman biteceğine karar vermek için daha iyi ve nesnel bir kriter olarak ne önerirsin? TDD'de olduğu gibi, test bir geliştiricinin hedeflediği özellik ise, test başarılı olduğunda geliştirici işini yapmıştır, değil mi? Evet, testte herhangi bir şartnamede kusurlar olduğu gibi kusurlar olabilir. Yine de geliştiricilerin görevi bu değil. Test hatalıysa düzeltilirse gelişim yeni hedefi hedef alır ve hepsi yeşil olduğunda yapılır. İşe yarıyor çünkü HER ZAMAN geçmek için bir test var ... fazladan, belgesiz kabartmak yok.
Edward Strange

3
Belki de kendimi açıkça ifade etmedim. Testler, ne zaman yapıldığını belirlemenin iyi bir yolu olabilir. Ne yapmaları gerektiğine karar vermenin iyi bir yol olduğunu sanmıyorum. TDD'de insanların ne yapmaları gerektiğine karar vermek için testler kullandıklarını görüyorum. Bu senin tecrüben mi?
CesarGon

Hayır. Binalarımız otomatikleştirildi. Değişiklikler tarafından tetiklenirler. Dediğim gibi, TDD çözümün sadece bir parçası.
Edward Strange

9

Önce tasarım

TDD, tasarım atlamak için bir bahane değil . "Çevik" bir çoğunluğa sıçrayan bir sıçrama gördüm, çünkü hemen kodlamaya başlayabileceklerini düşünüyorlardı. Gerçek çevik, şelale sürecine ilham veren (diğer alandaki) mühendislik uygulamalarından çok daha hızlı kodlama yapmanızı sağlar.

Ama erken test et

Biri testin tasarımı sürdüğünü söylerken, basitçe test aşamasının çok erken, testleri tamamlanmadan çok önce kullanılabileceği anlamına gelir. Bu testleri yapmak, gri alanları zorlayarak ve ürün tamamlanmadan çok önce gerçek dünyaya çarparak tasarımınızı güçlü bir şekilde etkiler. sizi sık sık tasarıma geri dönmeye ve bunu hesaba katacak şekilde uyarlamaya zorlamak.

Test ve tasarım ... bir ve aynı

Benim düşünceme göre TDD, testin sonunda geçerliliği onaylamak için yapılan bir şey yerine tasarımın ayrılmaz bir parçası olduğu sonucuna varıyor . TDD'yi gittikçe daha fazla kullanmaya başladığınızda, sisteminizi tasarlarken nasıl yok edeceğinizi / yıkabileceğinizi düşünürsünüz. Şahsen her zaman önce testleri yapmam. Elbette bir arayüz üzerinde belirgin (birim) testler yaparım, ancak asıl kazanımlar, bu tasarımın bozabileceği yeni ve yaratıcı bir yol düşündüğümde oluşturduğum entegrasyon ve spesifikasyon testlerinden geliyor. Bir yol düşündüğümde, bunun için bir test kodu ve ne olduğunu görüyorum. Bazen, bunun sonucuyla yaşayabilirim, bu durumda, testi ana yapının bir parçası olmayan ayrı bir projede taşıyorum (başarısızlığa devam edeceği için).

O zaman şovu kim sürdü?

TDD'de, burada sürülen testlerin basitçe testlerinizin o kadar güçlü bir şekilde etkilediği ve bir kişinin onu sürdüklerini hissedebilecekleri anlamına gelir. Ancak bu bir durur ve burada endişelerinizi anlıyorum, şovu yönlendiren kişi biraz korkutucu?

SİZ sürüyorsunuz, testleri değil. Testler oradadır, böylece ilerledikçe yarattığınız şeye iyi bir güven düzeyi kazandırırsınız, böylece sağlam zeminlere dayandığını daha da bilerek inşa etmenize izin verir.

Testler katı olduğu sürece katı

Tam olarak , bu nedenle TDD'de sürülür. Testler her şeyi yönlendirecek kadar değil, ancak işleri nasıl yaptığınız, sisteminizi nasıl tasarladığınız ve düşündüğünüz üzerinde çok büyük bir etkiye sahip olacak, düşünce sürecinizin büyük bir kısmını testlere ve karşılığında alacaksınız. tasarımınız üzerinde derin bir etkisi olacak.

evet ama bunu köprüsüm ile yaparsam ...

orada dur ... yazılım mühendisliği, diğer mühendislik uygulamalarından çok farklı. Aslında yazılım mühendisliği ile edebiyat arasında daha çok ortak nokta var. Biri bitmiş bir kitabı alabilir, 4 bölümden kopyalayabilir ve onları yeniden kitap haline koymak için iki yeni bölüm yazabilir ve yine de iyi bir kitabınız olur. İyi testler ve yazılımlar ile sisteminizin herhangi bir bölümünü koparabilir ve başka biriyle değiştirebilirsiniz ve bunu yapmanın maliyeti, ilk başta yarattığı kadar yüksek değildir. Aslında, testlerinizi yaptıysanız ve tasarımınızı yeterince etkilemelerine izin verdiyseniz, ilk etapta oluşturmaktan çok daha ucuz olabilir, çünkü bu değişimin testlerin kapsadığı şeyi kırmayacağına dair belirli bir güven seviyesine sahip olacaksınız.

Eğer sooo iyi ise nasıl oluyor her zaman işe yaramazsa?

Çünkü test yapmak, binadan çok farklı bir zihniyet gerektiriyor. Her biri geri dönüş yapamaz, aslında bazı insanlar doğru testler yapamazlar çünkü kendi yarattıklarını yok etmeye karar veremezler. Bu, hedef ölçümlere ulaşmak için yalnızca çok az sayıda test veya test içeren projeler sağlayacaktır (kod kapsamı akla gelir). Mutlu yol testleri ve istisna testlerinden memnun kalacaklardır, ancak köşe durumlarını ve sınır koşullarını unutacaklar.

Diğerleri sadece tasarımın kısmen veya tamamen yapılması için yapılan testlere dayanacaktır. Her üye bir şey yapıyor, sonra birbiriyle bütünleşiyor. Tasarım her şeyden önce bir iletişim aracıdır, bunun nerede olacağımı söylemek için belirttiğimiz paylar, bunun kapı ve pencerelerin olacağı yer olduğunu söyleyen eskizler. Bu olmadan yazılımınız, o maddeye yaptığınız kaç testten bağımsız olarak mahkumdur. Entegrasyon ve birleşme her zaman acı verici olacak ve en yüksek soyutlama seviyelerinde testlerden yoksun olacaklar.

Tor bu takımlar TDD gitmek için yol olmayabilir.


7

TDD ile test edilmesi kolay veya hızlı olmayan bir kod yazmama eğilimindedir. Bu küçük bir şey gibi görünebilir, ancak projeyi derinlemesine etkileyebilir, çünkü projeyi yeniden test etmenin, test etmenin, böcekleri test etmenin ve düzeltmeleri doğrulamanın ne kadar kolay olduğunu etkiler.

Ayrıca, testler tarafından desteklenen daha iyi faktörlü kodlara sahip olduğunuzda, projedeki yeni bir geliştiricinin hızlanması daha kolaydır.


2
Bundan hoşlanıyorum - faydaları yaratan TDD'nin (birim testlerinin açıkça büyük bir değere sahip olmasına rağmen) test edilebilir (yalıtılmış) anlamında ürettiği kod türü ve her türlü iyi şey bundan kaynaklanır (endişelerin ayrılması, IoC ve bağımlılık enjeksiyonu vb.)
Murph

1
@Murph evet TDD sizi dürüst tutmaya yardımcı olur :)
Alb

1
Dürüst olmak gerekirse, aslında "hızlandırmak daha kolay" argümanıyla ikna olmadım - testler yardımcı olabilir, ancak kodun (bir bütün olarak, kesinlikle yalıtılmaya gerek yok) kodunun çözülmesi biraz zor olabilir çünkü bazı şeyler çözecektir. sihirden geliyormuş gibi görünüyorsun, örneğin, IInjectedThing'in hangi uygulamasını kullandığını bilmiyorsun.
Murph

@Murph Teori, IInjectedThing uygulamasının iyi tasarlanmış ve iyi testlerle kapsanmasıdır, bu yüzden enjekte edildiği bir sınıfı anlayabilmenin ne olduğunu bilmenize gerek yoktur .
Adam Lear

@Anna - evet, bir noktaya kadar ... eğer bir şeyin kırıldığı yerde çalışmaya çalışıyorsanız (böcek avının her zaman bir projede yer alan kişileri bulmak için iyi bir yol olduğunu düşünüyorum) veya bir şeyin değiştirilmesi gerektiğini / nerede olduğunu bilmeniz gerektiğini de ekledi. İyi kapsüllenmiş olduğu yerde bile onu bulmanız gerekir ... ve bir şeyi değiştirmek anlamına gelirse (IWhatsit'in yeni uygulaması), o zaman alternatif uygulamanın nasıl kullanılacağını bilmeniz gerekir. Yine, inşaatın kötü olduğunu düşünmüyorum - aksine çok fazla kanıt - aksine bazı şeylerin daha az belirgin olabileceğini öne sürüyorum.
Murph

5

TDD'yi pratik yapmasam da bu konuda çok düşündüm. Kod kalitesi ile TDD'yi takip eden arasında (güçlü?) Pozitif bir korelasyon var gibi görünüyor.

1) Benim ilk aldığım şey, bunun (öncelikle) TDD'nin koda "daha iyi kalite" eklemesi (bunun gibi) olmamasından kaynaklanıyor, TDD'nin en kötü parçaları ve alışkanlıkları ayıklamasına yardımcı oluyor ve böylece dolaylı olarak kaliteyi arttırıyor.

Testin kendisinin olmadığını bile savunurum - bu testleri yazma sürecidir . Kötü bir kod için testler yazmak zordur ve bunun tersi de geçerlidir. Ve bunu programlama sırasında başın arkasında tutmak, birçok kötü kodu ortadan kaldırır.

2) Başka bir bakış açısı (bu felsefi oluyor) efendinin zihinsel alışkanlıklarını takip ediyor. Onun "dış alışkanlıklarını" izleyerek usta olmayı öğrenemezsiniz (uzun sakal iyidir), onun içsel düşünme yollarını öğrenmelisiniz ve bu zordur. Ve her nasılsa (acemi) programcılar TDD'yi takip ediyor, düşünce tarzlarını efendilerinkilere daha yakın hale getiriyor.


+1 Sanırım çivilenmiş, Maglob. “TDD'nin en kötü parçaların ve alışkanlıkların ayıklanmasına yardımcı olduğunu, […] dolaylı olarak kaliteyi arttırdığını” açıklamanızı özellikle seviyorum. Ve uzun sakal analojisi de çok iyidir.
CesarGon

hatalı bir kod için testler yazmazsınız, ancak bir test yazar ve testin geçmesini sağlamak için kod yazarsınız.

Maglob, olayların daha pratik tarafının aşkı için, onu en iyi şekilde ele geçirdin. @ Thorbjørn, bence Maglob, tasarladığınız tasarımın berbat etmesi durumunda testlerinizin kesinlikle emmek zorunda kalacağı, testlerinizin emiş seviyenizi emmek zorunda kalacağı ve çürük kokusunun daha önce testlerinizde koklamaları gerektiğini herhangi bir gerçek kod yazmaya bile inersiniz.
Filip Dupanović

3

"Geçti kadar test testi + refactor" yaklaşımı inanılmaz anti-mühendislik görünüyor.

Hem refactoring hem de TDD ile ilgili yanlış bir anlayışa sahip görünüyorsunuz.

Kod yeniden düzenleme , bir bilgisayar programının kaynak kodunu, yazılımın bazı işlevsel olmayan niteliklerini geliştirmek amacıyla dış işlevsel davranışını değiştirmeden değiştirme işlemidir.

Bu nedenle, geçinceye kadar kodu yeniden sorgulayamazsınız .

TDD, özellikle birim testi (diğer testler benim için makul gözüktüğü için temel gelişmeyi düşündüğüm gibi), bir bileşeni çalışana kadar yeniden tasarlamakla ilgili değil. Bir bileşen tasarlamak ve bileşen tasarlandığı gibi çalışana kadar uygulama üzerinde çalışmakla ilgilidir.

Ayrıca, ünite testinin test üniteleri ile ilgili olduğunu gerçekten anlamak önemlidir . Sıfırdan her zaman çok fazla şey yazma eğilimi nedeniyle, bu birimleri test etmek önemlidir. Bir inşaat mühendisi, kullandığı birimlerin özelliklerini (farklı malzemeler) zaten biliyor ve çalışmalarını bekleyebilir. Bunlar genellikle yazılım mühendisleri için geçerli olmayan iki şeydir ve kullanmadan önce birimleri test etmek için çok iyi bir mühendislik çalışması yapıyor çünkü test edilmiş, yüksek kaliteli bileşenler kullanmak anlamına geliyor.
Bir inşaat mühendisi bir stadyumu örtmek için çatı yapmak için bazı yeni fiber dokular kullanma fikrine sahipse, onu bir ünite olarak test etmesini beklersiniz, yani gerekli özellikleri (örneğin ağırlık, geçirgenlik, stabilite vb.) bundan sonra, onları karşılayana kadar test edin ve düzeltin.

TDD'nin çalışmasının nedeni budur. Çünkü, test edilmiş birimler yazılımı oluşturuyorsanız, şanslar çok daha iyidir, bunları bir araya getirdiğinizde ve sorunların yapıştırma kodunuzda olmasını bekleyemezseniz, testlerinizin iyi kapsamaya girdiğini varsayarsınız.

düzenleme:
Yeniden düzenleme anlamında: işlevlerde değişiklik olmaması . Birim yazı testinin bir noktası, yeniden düzenlemenin kodu ihlal etmemesini sağlamaktır. Bu nedenle TDD, yeniden yapılanmanın yan etkileri olmadığını garanti etmek içindir.
Taneciklilik bir perspektif konusu değildir çünkü dediğim gibi, birim tanecikleri tam olarak tanımlanmış olan test ünitelerini test eder, sistemleri test etmez.

TDD iyi mimariyi teşvik eder. Tüm birimleriniz için spesifikasyonları tanımlamanızı ve uygulamanızı gerektirir, sizi uygulama öncesinde tasarlamaya zorlar, bu sizin düşündüğünüzün tam tersidir. TDD, ayrı ayrı test edilebilecek ve bu nedenle tamamen ayrıştırılmış birimlerin oluşturulmasını belirler.
TDD, spagetti kodunda bir yazılım testi yaptığım ve pastayı geçene kadar karıştırdığım anlamına gelmiyor.

İnşaat mühendisliğine zıt olarak, yazılım mühendisliğinde genellikle bir proje sürekli olarak gelişir. İnşaat mühendisliğinde, A pozisyonunda, x ton taşıyabilecek ve saatte n araç için yeterince geniş bir köprü kurma zorunluluğu vardır.
Yazılım mühendisliğinde, müşteri temelde herhangi bir noktada (tamamlandıktan sonra) karar verebilir, iki katlı bir köprü istiyor ve en yakın otoyolla bağlantı kurmasını istiyor ve onun bir asansör köprüsü olmasını istiyor, çünkü şirketi Son zamanlarda yelkenli gemileri kullanmaya başladı.
Yazılım mühendisleri tasarımları değiştirmekle görevlidir . Tasarımları kusurlu olduğu için değil, modus operandi olduğu için değil. Yazılım iyi tasarlanmışsa, tüm düşük seviyeli bileşenleri yeniden yazmak zorunda kalmadan yüksek düzeyde yeniden tasarlanabilir.

TDD, ayrı ayrı test edilmiş, yüksek oranda ayrıştırılmış bileşenlere sahip yazılım oluşturma ile ilgilidir. İyi yürütülmüş, gereksinimlerdeki değişikliklere cevap vermemenizden çok daha hızlı ve daha güvenli şekilde yanıt vermenize yardımcı olacaktır.

TDD geliştirme sürecine gereksinimler ekler, ancak diğer kalite güvence yöntemlerini yasaklamaz. Verilen, TDD, resmi doğrulama ile aynı güvenliği sağlamaz, ancak daha sonra, resmi doğrulama, son derece maliyetli ve sistem düzeyinde kullanmak imkansızdır. Ve yine de istersen ikisini de birleştirebilirsin.

TDD ayrıca, sistem düzeyinde gerçekleştirilen birim testleri dışındaki testleri de kapsar. Bunları açıklaması kolay, ancak uygulaması zor ve ölçülmesi zor buluyorum. Ayrıca, oldukça makul. Gereksinimlerini kesinlikle görmeme rağmen, onlara gerçekten fikir olarak değer vermiyorum.

Sonunda hiçbir araç aslında bir sorunu çözmez. Araçlar sadece bir problem çözmeyi kolaylaştırır. Sorabilirsiniz: Bir keski, harika bir mimariye nasıl yardımcı olur? Düz duvarlar yapmayı planlıyorsanız, düz tuğlalar yardımcı olacaktır. Ve evet, kabul edildi, eğer o aleti bir salaka verirseniz, muhtemelen sonunda ayağından atar, ama bu keskilerin suçu değil, TDD'nin acemilere yanlış güvenlik sağladığı bir kusur olmadığı sürece, kim iyi testler yazmaz.
Sonuç olarak, TDD'nin TDD'den çok daha iyi çalıştığını söyleyebiliriz.


Bir yanılgı olduğunu sanmıyorum; Gönderdiğiniz kod yeniden düzenlemesinin tanımına katılıyorum, ancak koddaki değişikliklerin ayrıntı derecesine bakmanız gerektiğini de düşünüyorum. " Bir bilgisayar programının kaynak kodunu değiştirme işlemi" derken , belli bir bütünün bakış açısından davranışın değişmediğini, ancak parçaların davranışının gerçekten değiştiğini fark etmeniz gerekir. Değişimin bu şekilde gerçekleşmesidir. Bunun yanı sıra, TDD'nin neden çalıştığını (ve paylaşıyorum) sizi duyuyorum, fakat mimarlık orijinal görevime göre nasıl ele alınmaktadır?
CesarGon

@CesarGon: Yayın güncellendi.
back2dos

2

'Kullanıcı yerine test yerine' şartı koyar 'demekten hoşlanmıyorum. Sanırım sadece TDD'de birim test yapmayı düşünüyorsunuz, bununla birlikte entegrasyon testini de kapsıyor.

Yazılımın temelini oluşturan kütüphaneleri test etmenin yanı sıra, kullanıcılarınızın yazılım / web sitesiyle olan etkileşimlerini kapsayan testleri yazın. Bunlar doğrudan kullanıcılardan geliyor ve salatalık (http://cukes.info) gibi kütüphaneler, kullanıcılarınızın testleri kendi dillerinde doğal dilde bile yazmalarına izin veriyor.

TDD ayrıca kodda esnekliği de teşvik eder - sonsuza dek bir şeyin mimarisini tasarlamak için harcıyorsanız, bu değişiklikleri yapmak için daha sonra gerektiğinde inanılmaz zor olacak. Birkaç test yazmaya başlayın, sonra bu testleri geçen küçük bir kod yazın. Daha fazla test ekleyin, daha fazla kod ekleyin. Kodu kökten değiştirmek zorunda kalırsanız, testleriniz hala geçerli.

Ve köprülerden ve arabalardan farklı olarak, tek bir yazılım parçası ömrü boyunca büyük değişikliklere uğrayabilir ve ilk önce yazılı testlere tabi tutulmadan karmaşık yeniden yapılandırma yapmak sadece sorun istiyor .


TDD için iddia ettiğin faydalardan seni duyuyorum. Ancak anladığım kadarıyla, sorumu açıkça sorduğum mimari ve test kalitesi konularına değinmiyorsunuz.
CesarGon

@CesarGon: Sanırım özel sorularınız sadece TDD için değil, her türlü test için geçerli. Bu yüzden sadece TDD'nin 'işe yarayan' özelliklerine odaklandım.
sevenseacat

1
Entegrasyon testleri kesinlikle bağımsız ünite testlerinden daha anlamlı. Karşılaştığım çoğu hata vakası, hiçbir zaman gerçek sistemi tüm cıvataları ve ıslıkları ile birlikte test ederek ünite testlerinde bulunmazdı .

2

Sanırım ilk noktaya yanlış açıdan yaklaşıyorsun.

Teorik açıdan bakıldığında, bir şeyin başarısızlık noktalarını kontrol ederek çalıştığını kanıtlıyoruz. Kullanılan yöntem budur. Bir şeyin işlevsel olduğunu ispatlayabilmeniz için başka yollar olabilir, ancak TDD bit-akıllı yaklaşımının sadeliği nedeniyle kendisini kanıtladı: eğer kırılmazsa çalışır.

Uygulamada, bu açıkça açık bir şekilde tercüme edilir: şimdi bir sonraki şeye geçebiliriz (tüm tahminleri yerine getirmek için TDD'yi başarıyla uyguladıktan sonra). TDD'ye bu perspektiften yaklaşıyorsanız, o zaman bu " tamamlamadan önce testler + refactor yazmak" ile ilgili değildir, bunu daha çok tamamlamış olmaktayım, şimdi tamamen en önemli şey olarak bir sonraki özelliğe odaklanıyorum .

Bunun inşaat mühendisliği için nasıl geçerli olduğunu düşünün. 150000 kişilik bir halk kitlesine ev sahipliği yapabilecek bir stadyum inşa ediyoruz. Stadyumun yapısal bütünlüğünün sağlam olduğunu ispatladıktan sonra, önce güvenliği sağladık . Artık tuvaletler, yemek standları, koltuklar vb. Gibi hemen önemli olan diğer konulara odaklanabiliriz ... izleyicinin deneyimini daha zevkli hale getirmek için. TDD'nin çok daha fazlası olduğu için bu bir aşırı basitleştirmedir, fakat işin aslı, hem yeni hem de heyecan verici özelliklere odaklanmak ve aynı zamanda bütünlüğü korumak için mümkün olan en iyi kullanıcı deneyimini yaşamadığınızdır. Her iki durumda da yarım yoldan olsun. Yani, nasıl olduğunu tam olarak nasıl bilebilirsinBirçok tuvaleti ve 150000 kişiyi nereye yerleştirmelisiniz? Stadyumların kendi ömrümde çöküşünü nadiren görmüştüm, ancak çoğu zaman yarı zamanlı sırada beklemek zorunda kaldım. Bu, tuvalet sorununun tartışmasız daha karmaşık olduğunu ve mühendislerin güvenlik için daha az zaman harcayabilecekleri takdirde, sonunda tuvalet sorununu çözebileceklerini söylüyor.

İkinci noktanız ilgisiz, çünkü zaten mutlaklıkların aptalların çabaları olduğu konusunda hemfikirdik çünkü Hank Moody onların var olmadığını söylüyor (ama bunun için bir referans bulamıyorum).


+ 1 puanımın iyi bir açıklaması ve Hank Moody’nin referansı için. Şanlı.
CesarGon

2
Teşekkürler bunun için minnettarım. TDD'yi teknik bir yaklaşım / süreçten çok psikolojik bir fenomen olarak görüyorum. Ama bu sadece konuya ilişkin dünya görüşüm.
Filip Dupanović

Kaç tane tuvaleti ve nereye yerleştirilmeleri gerektiğini tam olarak biliyor musunuz? Cevap evet - gidip herhangi bir mimara sorun ve size bu bilginin daha önceden yapıldığını ve bazen de desteklenmesi için net istatistik verilerinin verildiğini söyleyecekler.
gbjbaanb 14:13

1

Yazılım mühendisliğinde TDD iyi bir uygulamadır, aynı şekilde uygulamalardaki hata yönetimi, kayıt ve teşhis işlemlerinin yanı sıra (hata işlemenin bir parçası olmasına rağmen) iyi bir uygulamadır.

TDD, yazılım geliştirmeyi deneme yanılma kodlamasına indirgeme aracı olarak kullanılmamalıdır. Ancak yine de çoğu programcı, çalışma günlüğüne bakar, hata ayıklayıcıdaki istisnaları izler veya tüm gün boyunca uygulamayı kodlayan / derleyen / çalıştıran uygulama aşamalarında diğer hata / başarı belirtilerini kullanır.

TDD, sizi geliştirici olarak daha üretken kılmak için bu adımları resmileştirmenin ve otomatikleştirmenin bir yoludur.

1) Yazılım mühendisliğini köprü inşasıyla karşılaştıramazsınız, köprü inşasında esneklik bir yazılım programı tasarlamanın yanında değildir. Köprüyü inşa etmek aynı programı tekrar tekrar kayıplı bir makineye yazmak gibidir. Köprüler kopyalanamaz ve yazılımın kullanabileceği şekilde yeniden kullanılamaz. Her köprü benzersizdir ve üretilmesi gerekir. Aynı arabalar ve diğer tasarımlar için de geçerli.

Yazılım mühendisliğinde en zor olan şey, hataların çoğalmasıdır, bir köprü bozulduğunda genellikle neyin yanlış gittiğini belirlemek çok kolaydır ve teoride başarısızlığı yeniden oluşturmak kolaydır. Bir bilgisayar programı başarısız olduğunda, sistemi hatalı duruma getiren karmaşık bir olaylar zinciri olabilir ve hatanın nerede olduğunu belirlemek çok zor olabilir. TDD ve birim testi, yazılım bileşenlerinin, kütüphanelerin ve algoritmaların sağlamlığını test etmeyi kolaylaştırır.

2) Yanlış güven duygusu oluşturmak için sistemi zorlamayan zayıf ünite testleri ve sığ test durumları kullanmak sadece kötü bir uygulamadır. Bir sistemin mimari kalitesini görmezden gelmek ve sadece testleri yerine getirmek elbette kötüdür. Fakat inşaat alanında aldatma, gökdelen veya köprüden malzeme tasarrufu yapmak ve planları takip etmemek için kötüdür ve her zaman olur ...


Fiziksel (yani yazılım dışı) sistemlerde arızaların çoğaltılmasının kolay olduğu fikrine katılmıyorum. Örneğin, trafik kazalarındaki mekanik arızaların temel nedenlerini belirlemek için gerekli olan son derece karmaşık ve sıkı çalışmaya bakın .
CesarGon

Hm, şimdi çökmekte olan bir Havayolunu başarısız bir köprü ile karşılaştırıyorsunuz, bir köprü genellikle uçamıyor, dava kapanıyor. Ancak uçaklarla yazılım arasındaki karşılaştırma bazen geçerlidir. Her iki alan da çok karmaşık ve yapılandırılmış bir test metodolojisi gerektiriyor. Böylece bir köprü bozulduğunda, aşırı yüklendiğini biliyorsunuzdur. Bir uçak çöktüğünde, anormal uçma noktasının yerden uçmasının başarısız olduğunu biliyorsunuzdur, ancak bunun nedeni genellikle yazılım arızası ile aynı şekilde derinlemesine bir araştırma yapılmasını gerektirir.
Ernelli

Köprüler çoğaltılabilir - ya da en azından mimardan satın aldığınız köprü planı kabaca, tam olarak sizin koşullarınıza uygun modifikasyonlar yapabilir. Mesele şu ki, eğer bir köprüye ihtiyacınız varsa, mimarın yanına gideceksiniz ve size sahip olabileceğiniz sadece birkaç tipin bir listesini verecek - askıya alma, kutu, kemer vb.
gbjbaanb

1

Hataların ne kadar erken tespit edildiğini kabul ederseniz, onları tamir etmenin maliyeti düşer, o zaman bu tek başına TDD'yi değerli kılar.


1
TDD ortamında böceklerin daha önce bulunduğuna dair herhangi bir kanıtınız var mı? Ayrıca, TDD'nin mimarlık üzerindeki etkisi gibi yan etkileri nelerdir?
CesarGon

0

TDD gerçekten test yapmaktan ibaret değil. Ve kesinlikle iyi testlerin yerini almaz. Size sunduğu şey, iyi düşünülmüş, tüketicinin tüketmesi kolay, daha sonra bakımı ve yenilemesi kolay bir tasarım . Bu şeyler daha az hataya ve daha iyi, daha uyumlu bir yazılım tasarımına yol açar. TDD aynı zamanda varsayımlarınızı düşünmenize ve belgelendirmenize yardımcı olur, çoğu zaman bunların yanlış olduğunu tespit eder. Bunları süreçte çok erken buluyorsunuz.

Güzel bir yan fayda olarak, bir yeniden yapılandırmanın yazılımınızın davranışını (girişler ve çıkışlar) değiştirmemesini sağlamak için gerçekleştirebileceğiniz büyük bir testler paketiniz var.


6
-1. Birçok insan bunu söylemeye devam ediyor, ama ben bunu gerçekleştiren büyüyü henüz görmedim.
Bart van Ingen Schenau

@Bart van Ingen Schenau, TDD'yi yaptınız mı? Yaklaşık 4 yıldır bu işi yapıyorum ve kesinlikle "sihrin" olduğunu gördüm.
Marcie

0

Size kısa bir cevap vereceğim. Tipik olarak TDD, ünite testlerinde olduğu gibi yanlış şekilde incelenir. İyi bir teknik konuşma videosu izledikten sonra yakın zamana kadar ünite testini hiç anlamadım. Temelde TDD sadece aşağıdakilerin ÇALIŞMASI istediğinizi belirtiyor. Uygulanmaları GEREKİR. Sonra yazılımın kalanını normalde yaptığınız gibi tasarlarsınız.

Bir nevi yazma biçimi, kütüphane tasarlamadan önce kütüphane için davalar kullanır. Bunun dışında bir kitaplıktaki kullanım durumunu değiştirebilirsin ve TDD için olmayabilir (API tasarımı için TDD kullanıyorum). Daha fazla test eklemeniz ve testin alabileceği vahşi girdiler / kullanımlar hakkında düşünmeniz de tavsiye edilir. Bir şeyi değiştirirseniz bir şeyi bozduğunuzu bilmeniz gereken kütüphaneleri veya API'leri yazarken yararlı buluyorum. Gündelik yazılımların çoğunda rahatsız etmiyorum çünkü bir düğmeye basarak kullanıcı için bir test vakasına ihtiyacım var ya da CSV listesini veya satır başına bir giriş içeren bir listeyi kabul etmek istersem ... İzin vermem gerçekten önemli değil böylece değiştirmek için TDD kullanmamalı / kullanmamalıyım.


0

Yapısal mühendislik beton olduğunda yazılım organiktir.

Köprünüzü kurduğunuzda, köprü kalacak ve kısa bir süre içinde başka bir şeye dönüşmesi muhtemel değildir. İyileştirmeler aylar ve yıllar boyunca yapılacak, ancak yazılımdaki gibi saatlerce ve günlerde yapılmayacak.

İzolasyonda test yaptığınızda normalde kullanabileceğiniz iki tip çerçeve vardır. Kısıtlanmış çerçeve ve kısıtlanmamış. Sınırlandırılmamış çerçeveler (.NET'te), erişim değiştiricilerden bağımsız olarak her şeyi test etmenize ve değiştirmenize olanak sağlar. Yani, özel ve korumalı bileşenleri saplayıp alay edebilirsiniz.

Gördüğüm projelerin çoğunda sınırlı çerçeveler kullanılıyor (RhinoMocks, NSubstitute, Moq). Bu çerçevelerle test ederken, uygulamanızı çalışma zamanında bağımlılıkları enjekte edip yerine koyacak şekilde tasarlamanız gerekir. Bu, gevşek bağlantılı bir tasarıma sahip olmanız gerektiği anlamına gelir. Gevşek bir şekilde birleştirilmiş tasarım (doğru yapıldığında) endişelerin daha iyi ayrılması anlamına gelir, bu iyi bir şeydir.

Özetlemek gerekirse, bunun arkasındaki düşüncenin, tasarımınızın test edilebilir olması durumunda, gevşek bir şekilde bağlı olduğu ve endişelerin iyi bir şekilde ayrıldığına inanıyorum.

Bir yandan, gerçekten test edilebilir, ancak nesneye yönelik tasarım perspektifinden kötü yazılmış uygulamalar gördüm.


0

TDD neden çalışıyor?

Öyle değil.

Açıklama: otomatikleştirilmiş testler hiçbir testten daha iyidir. Bununla birlikte, şahsen, çoğu kez totolojik oldukları (yani test altındaki gerçek koddan açıkça anlaşılan şeyler olduğunu söyleyen) birim testlerinin çoğunun atık olduğunu düşünüyorum. ).

Ve en önemlisi: İyi yazılım tasarımı, birçok çevik / TDD saldırganının ilan ettiği gibi sihirli bir şekilde testten düşmez. Aksi takdirde iddiada bulunan herkes, bunu kanıtlayan hakemli bilimsel araştırmalara bağlantılar sunar ya da en azından TDD'nin yararlarının potansiyel olarak kod değişikliği tarihiyle araştırılabileceği bazı açık kaynaklı projelere atıfta bulunur.

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.