Test Driven Development - suckerman7/JavaRestAPI-Demo GitHub Wiki
Test Driven Development Nedir?
Test Driven Development, namı diğer Test Güdümlü Geliştirme, Kent Beck tarafından Extreme Programming adı altında bulunmuş bir programlama tekniğidir. Bu kavramın bulunuş tarihi olarak 1994 yılını işaret edebiliriz. Beck o yılda SmallTalk için SUnit isimli bir test framework'ünü yazmıştır. 1998 yılında ise Beck, "testleri çoğunlukla ilk sırada yazmalıyız" diyerek Test First adlı bir kavram ortaya atmıştır.
Test Driven Development kavramı, en iyi şekilde 2002 yılının Kasım ayında basılan Test Driven Development: By Example isimli kitapta teknik olarak ele alınmıştır. Üzerinden seneler geçmesine rağmen yine de bu konuyu öğrenmek isteyenler için birincil kaynak konumunu korumaktadır.
Test Driven Development Nasıl Çalışır?
Yukarıdaki resimde bahsedildiği gibi Test Driven Development, birden fazla aşamada basitçe halledilir:
1. Bir test yazılır.
2. Yazılan test başarısız olur.
3. Test başarılı hale getirilir.
4. Mevcut aşamadaki bütün testlerin başarılı olması sağlanır.
5. Ve en sonunda kod, "refactor edilir".
Bu aşamaları ele aldıktan sonra şunu belirtmek isterim ki: TDD, önceden kodu yazmak ve sonra kodu test etmek değildir. TDD ile ilgileniyorsanız kesinlikle ilk olarak test işini halletmelisiniz. Ama yanlış anlamayın ki her developer veya ekip, TDD kullanmak zorunda değildir. Eklemek gerekirse** elde mevcut bulunan kodlar için de test yazılması** çok önemlidir.
Peki test yazmak bu kadar önemliyse... Testleri önceden veya sonradan yazmak yazılımcıya ne kadar katma değeri bulunur?
Test Driven Development ve Katmanlı Mimari
Her ne kadar TDD kavramını Test Driven Development olarak açsak bile birçok üstat bunu Test Driven Design olarak da ifade eder. Geleneksel uygulama geliştirme tekniklerinde yazılımcının önüne bir ister geldiğinde Bottom to Top Approach diye ifade ettiğimiz tekniği kullanırlar.
Eğer yazılımcının katmanlı mimariyle geliştirme yaptığını ele alırsak, yukarıda bahsettiğimiz tekniği katmanlı mimarinin en altından başlayıp en üst katmana doğru yaklaşımı olarak tanımlayabiliriz.
Şimdi örnek olarak bir ödeme sistemi tasarlamak istersek:
1. Önce veritabanını düşünür, bunlara göre gerekli tablolar ve tabloların kolonları tasarlanır.
2. Sonra 3 katmanlı mimaride bir üste çıkıp "İş Katmanı" kodlanır.
3. Sonra da "Sunum Katmanı" kodlanır.
4. Ve en son olarak da yazılan uygulama, Sunum Katmanından test edilir.
Eğer herhangi bir katmanda hata ortaya çıkarsa ve giderilirse yine Sunum Katmanı içinde Manuel Test yapılmaya devam edilir.
Aşağıdaki resimde programlama sırasında ortaya çıkan bir Bug'ın maliyetinin SDLC'de hangi fazda ne kadar olduğu görülmektedir:
TDD ile hataları minimize etmek
Yukarıdaki resimi ele alırsak, uygulamanın içinde çıkan Bug'ları uygulama PROD'a çıkmadan bulup çözebilirsek PROD sonrası oluşacak maliyetleri de o kadar azaltabiliriz.
TDD'nin sunduğu en önemli katma değer KISS (Keep it Simple, Stupid) adlı bir prensiptir. Yani isimden anladığımız kadarıyla programladığımız her şeyi basit tutmalıyız. Buna hem kod hem de oluşan mimariler de dahildir.
Eğer yukarıdaki örnek verdiğimiz developer, bu isterde TDD kullanmış olsaydı; "top to bottom" yaklaşımını kullanmış olacaktı. Yani bakış açısını 180 derece değiştirmek zorunda kalacaktı.
1. Öncelikle sunum katmanında bir test yazılır. Bu yazacağımız test, sadece Sunum Katmanını ilgilendirir. Aşağıda bulunan katmanlar daha dahil değildir.
2. Bir alt katmanda, iş kurallarını test eden testler yazılır ve bu katmanda sadece "içerde bulunan kodlar" test edilir. Şu an herhangi bir şekilde veritabanı ile ilgili bir bilgi daha yoktur.
3. Ve en altta "Repository katmanında" artık mevcut tasarımımıza ait veritabanı oluşturulur.
Eğer bu iş sonunda uygulamada yine bug'lar ortaya çıkarsa onlar hemen düzeltilir ve yazılmış testler tekrardan çalıştırılır. Artık testlerimiz otomatize olduğu için geliştirme döngüsü büyük bir oranda hızlanır. Artık bu noktada test yazmanın hala bir maliyeti olduğu düşünülebilir ama 2 veya 3 defa manuel test yaparken harcanılan süre arasında hiçbir fark yoktur. Eğer yazılımı yaşayan bir organizmaya benzetirsek, uzun bir süre boyunca bu testler büyük miktarda çalıştırılacaktır.
Refactoring ve TDD
Yaptığımız testleri başarıyla sonuçlandırma safhasında önemli olan şey, testlerin rahat geçmesidir. Yazdığımız kodlarda yer alan IF veya ELSE kodları, mükerrer kodlar olabilir. Ancak bu süreçten sonra bunların bizi endişelendirmemesi gerekir. Çünkü elimizde artık otomatize testler mevcuttur. Bu safhadan sonra TDD'nin bizim için sunduğu en önemli olan özellik Refactoring kısmı devreye girer. Bu kısım, istediğimiz zaman yapılabilir.
Yukarıdaki resime göz atarsak süreçlerde testler iyileştirilip çalıştırılmaya devam edilir. Bunun sonucunda ise sürekli iyileştirilmeye eğimli bir kodlar bütünü ortaya çıkar. Her testi yazıp başarıyla tamamladıktan sonra VCS'de kodları uygun mesajları yazarak commit'lemek büyük bir miktarda faydalı olacaktır.
Sonuç olarak, TDD'yi basit kod yazarken, basit tasarım yaparken ve düzenli olarak refactoring yaparken kullandığımız bir pratik olarak özetleyebiliriz.
REFERANSLAR:
https://medium.com/@nerobianchi/tdd-nedir-965c1a26e68f
https://www.typemock.com/blog/the-cost-of-test-driven-development/