TDD nedir?

Erdem OZDEMIR
4 min readJan 2, 2018

--

Merhaba bu yazıda TDD’nin ne olduğunu anlatmaya çalışacağım.

Test Driven Development olarak ifade edeceğimiz TDD’yi Türkçe’ye Test Güdümlü Geliştirme olarak çevirebiliriz.

Kent Beck tarafından Extreme Programming’in bir parçası olarak bulunmuş olan bir programlama tekniğidir. Tarih açısından bakacak olursak 1994 yılında Beck, Smalltalk için SUnit test framework’ünü yazmıştır. 1998 yılında XP’de “testleri çoğunlukla ilk sırada yazmalıyız” diye ifade ettiği Test First kavramını ortaya artmıştır. 2002 Kasım’ında piyasaya çıkan Test Driven Development: By Example isimli kitabında Test-First kavramını Test Driven Development olarak daha da detaylı bir teknik olarak ele alınmıştır. Üzerinden 15 yıl geçmiş olmasına rağmen TDD öğrenmek isteyenlere hala bir başucu kılavuzu olarak yer almaktadır.

https://www.whizlabs.com/wp-content/uploads/2016/04/TDD.png

Resimde göreceğimiz üzere TDD çok basit bir kaç adımdan oluşmaktadır.

1. Bir test yazılır.
2. Test başarısız olur.
3. Test başarılı hale getirilir.
4. Mevcut bütün testlerin başarılı olması sağlanır.
5. Kod refactor edilir. Yani kodda iyileştirme ve(ya) temizleme yapılır.

Bu bağlamda önceden kodu yazıp sonradan bunların testini yazmanın TDD olamadığını özellikle belirtmek gerekmektedir. TDD’de mutlaka ama mutlaka test ilk sırada yazılmalıdır. Tabii her ekip yada her yazılımcı TDD yapmak zorunda değildir. Mevcut kodları için test yazılmasının da bir o kadar önemli olduğunu eklemek önemli olacaktır.
Peki test yazmak önemli ise testleri önceden yazmak ile sonradan yazmak yazılımcıya nasıl bir katma değer katacaktır?

Her ne kadar TDD’yi Test Driven Development olarak açsakta bir çok üstat bunu Test Driven Design olarak da ifade etmektedir.

Geleneksel uygulama geliştirme tekniklerinde yazılımcının önüne bir ister geldiğinde “bottom to top approach” diye ifade ettimiz tekniği kullanır. Yazılımıcının katmanlı mimari ile geliştirme yaptığını ele alırsak. Katmanlı mimarinin en alt katmanlarından başlayarak en üst katmana doğru geliştirme yaklaşımı olarak tanımlayabiliriz.
Örnek olarak, bir ödeme sistemi tasarlanmak istendiğinde yazılmcı
1. Önce veritabanını düşünür, gerekli tabloları ve bunların kolonları tasarlar. Mesela isterde sadece kredi kartı ile ödeme yapıldığını analiz edilmesine rağmen ileride başka ödeme tipleri de gelebileceğini düşünerek o ödeme tipleri içinde alanlar oluşturdu.
2. Sonra 3 katmanlı mimari de bir üste çıkarak İş Katmanını kodlar
3. Ve en son olarak Sunum Katmanını kodlar.
4. Uygulamayı Sunum Katmanı üzerinden test eder.

Eğer hangi katmanda olursa olsun bir hata çıkarsa hata giderildikten sonra gene Sunum katmanından manuel test yapılmaya devam eder.
Ama mevcutta sadece kredi kartı ile ödeme olmasına rağmen diğer ödeme tipleri de test edildi. Bu bağlamda kodda ihtiyaç olmamasına rağmen fazladan kodlar bulunmuş oldu ve kodumuz gereksiz karmaşık aldı.

Aşağıdaki resimde bir bug’ın maliyetinin SDLC’de hangi fazda ne kadar olduğu görülmekte.

https://www.typemock.com/blog/the-cost-of-test-driven-development/

Bu bağlamda bug’ları uygulama PROD’a çıkmadan bulup, çözebilirsek maliyetleri de o kadar azaltabilme şansına sahip oluruz.

TDD’nin sunduğu en önemli katma değer KISS (Keep It Simple Stupid) prensibidir. Yani her şeyi basit tutmalıyız. Bu yazılan kodlar ve hatta mimari için de geçerlidir.
Eğer ilgili yazılımcı bu isterde TDD kullanmış olsaydı “top to bottom” yaklaşımını kullanmış olacaktı. Yani bakış açısını 180 derece değiştirmek zorunda kalacak.
1. Sunum katmanında bir test yazılır. Elimizde sadece kredi kartı ile ödeme olduğundan sadece kredi kartı ile ödeme şartını sağlayan bir test olmalıdır. Bu test sadece sunum katmanını ilgilendirmelidir. Aşağıdaki katmanlardaki kodlar henüz bulunmamaktadır.
2. Bir alt katmanda İş kurallarını test eden testler yazılır ve burası da sadece bu katmandaki kodları test eder. Her hangi bir şekilde veritabanı ile bir bilgi yoktur.
3. En altta Repository katmanında artık mevcut tasarımımıza ait veritabanı oluşturulur.

Eğer yeni uygulamada bir bug çıkarsa bug düzeltilir ve yazılmış testler tekrardan çalıştırılır. Artık otomatize testlerimiz olduğu için geliştirme döngümüz hızlamaya başladı. Bu noktada test yazmanın bir maliyeti olacağı düşünülebilir ama 2 yada 3 defa manuel test yaparken harcanan süre test yazmak ile hemen hemen aynıdır. Yazılımın yaşayan bir organizmaya benzetirsek uzun süre boyunca bu testler çok sayıda çalıştırılacaktır.

Örnekte eğer yeni bir ödeme tipi geldiğinde bu ödeme tipi ile ilgili geliştirme döngüsü yukarıdaki gibi tekrar eder. Ve tasarım ilgili isteklere göre evrimleşir.

Testlerimizi başarılı ile sonuçlandırma safhasında önemli olan testlerin geçmesidir. Kodlarımızda if’ler else’ler mükerrer kodlar olabilir. Bunlar artık bizi endişelendirmemektedir. Çünkü elimizde artık otomatize testlerimiz var. Bu noktadan sonra TDD’nin bizim için sunduğu en önemli özellik olan REFACTORING kısmı devreye girmektedir. Bu istenildiği kadar yapılabilir.

https://upload.wikimedia.org/wikipedia/commons/0/0b/TDD_Global_Lifecycle.png

Yukarıdaki resimde da görüldüğü üzere iyileştirme yapılıp testler çalıştırılır. Artık elimizde sürekli iyileştirmeye uygun bir kodlar bütünü oluşmaya başladı.
Her bir testi yazdıktan ve başarılı bir şekilde tamamladıktan sonra VCS’de kodları uygun mesaj ile commit’lemek faydalı olacaktır.

https://www.typemock.com/blog/the-cost-of-test-driven-development/

Yukarıdaki resim çeşitli kurumlardaki TDD uygulandığında ve uygulanmadığındaki karşılaştırmayı göstermektedir.

Sonuç olarak TDD’yi; basit kod yazmamızı, basit tasarım yapmamızı ve düzenli olarak refactoring yapmamızı sağlayan bir pratik olarak özetleyebiliriz.

Kaynaklar;
https://www.typemock.com/blog/the-cost-of-test-driven-development/
http://www.macqueen.us/smalltalkReport/ST/91_95/SMAL0402.PDF
https://www.agilealliance.org/glossary/tdd/
https://en.wikipedia.org/wiki/Kent_Beck

--

--

Erdem OZDEMIR

A husband, a father of two daughters and an enthusiast software engineer