# Test Driven Development (T.D.D.)

### 1. Kaynaklar

* [Test Driven Development: By Example, *Kent Beck (2002)*](https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530)
* <http://www.extremeprogramming.org/rules/testfirst.html>
* <https://www.wikiwand.com/en/Test-driven_development>
* <https://www.agilealliance.org/glossary/tdd/>
* <https://medium.com/@nerobianchi/tdd-nedir-965c1a26e68f>
* <https://codeutopia.net/blog/2016/10/10/5-step-method-to-make-test-driven-development-and-unit-testing-easy/>

### 2. Tanım

Kod geliştirmeden önce testlerini yazarsanız, göreceksiniz ki kodu oluşturmanız çok daha kolay ve hızlı olacak. Bir birim testi oluşturmak ve testin geçmesini sağlayacak kodu yazmanın toplamı, sadece kodu doğrudan yazmanız ile neredeyse aynı zamanı alacak. Ancak zaten birim testleriniz varsa, kodu yazdıktan sonra onları oluşturmak için zaman harcamayacaksınız ve daha sonrası için daha da fazla zaman kazanacaksınız.

Bir birim testi oluşturmak, geliştiricinin ne yapılması gerektiğini gerçekten düşünmesine yardımcı olur. Gereksinimler testlerle sıkı bir şekilde baştan sabitlenmiştir. Çalıştırılabilen kod formunda yazılan bir spesifikasyon konusunda yanlış anlaşılma olamaz.

Ayrıca, çalışırken anında geribildirim de alırsınız. Bir geliştiricinin gerekli işlevi geliştirmesinin tamamlanıp tamamlanmadığı konusunda genelde bir belirsizlik vardır. Olası genişletmeler ve hata durumları da düşünüldüğünde gerekli kapsamın aşılması (scope creep) durumu oluşabilir. Ancak birim testlerimizi önce yazarsak, ne zaman bitirdiğimizi biliriz; tüm birim testleri geçer.

Önce testi geliştirmenin sistem tasarımı için de bir yararı vardır. Genelde bazı yazılım sistemlerinin birim testlerini oluşturmak zordur. Bu sistemlerin genelde önce kodları, sonra testleri yazılır, sıklıkla da tamamen başka bir takım tarafından. Testleri önce yazarak, müşterinize değer katacak her şeyi test etme arzusundan etkilenen bir tasarımınız olacaktır. Tasarımınız daha kolay test edilecek şekilde oluştuğundan, bu isteği yansıtır hale gelecektir.

Testin yönlendirdiği yazılım geliştirmenin bir **ritmi** vardır. Önce elimizdeki sorunun küçük bir görünümü hakkında bir test oluştururuz. Sonra testin geçmesini sağlayacak **en basit kodu** yazarız. Sonra ikinci bir test oluştururuz. Sonra bu yeni testin de geçmesini sağlayan kodu ekleriz, ama **daha fazlasını değil!** Üçüncü bir testimiz olana kadar daha fazlasını yazmayız. Geçecek test kalmayıncaya kadar devam ederiz.

![](https://2987934822-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMVhHkJTh1jcl5YdqbV%2F-MM_aMVB0lB-ECiSA7Ws%2F-MM_ajHCfACvsCXbYA8g%2FTest-driven_development-rhythm-simple.png?alt=media\&token=8b1de8b0-d35c-49f3-962a-8634bb7c3e0c)

Oluşturacağınız kod kısa ve öz olacak, sadece istediğiniz özellikleri sağlayacak. Diğer geliştiriciler testleri inceleyerek bu yeni kodu nasıl kullanacaklarını öğrenecekler. Sonuçları tanımlanmamış girdiler bariz bir şekilde test suitinde yer almayacaklar.

Testin yönlendirdiği geliştirmenin sonucunda bizim için sunduğu en önemli özellik olan [Refactoring - Yeniden Düzenleme](https://bekoturko.gitbook.io/yazilim-gelistirme-wiki/yazilim-gelistirme-kilavuzu/refactoring) süreci devreye girer. Bu süreç istenildiği kadar uygulanabilir.

Sonuç olarak Testin Yönlendirdiği Geliştirmeyi (TDD) basit kod yazmamızı, basit tasarım yapmamızı ve düzenli olarak refactoring yapmamızı sağlayan bir pratik olarak özetleyebiliriz.

### 3. Testin Yönlendirdiği Programlama Ritmi

![](https://2987934822-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMVhHkJTh1jcl5YdqbV%2F-MM__IXIvXWKmFMZpHny%2F-MM__c8XNU7NJVH2QrJ_%2FTest-driven_development-rhythm.png?alt=media\&token=d1b793e2-1679-4d18-a4f7-d195f16a3a9a)

1. İşlevi geliştirmeden önce işlevin testini yaz.
2. Testi çalıştır ve testin geçmediğini (kırmızı çubuk) gör.
3. Sadece testin geçmesini sağlayacak kadar uygulama kodu yaz. Testin geçtiğini (yeşil çubuk) gör.
4. Kodu düzenle ([Refactoring - Yeniden Düzenleme](https://bekoturko.gitbook.io/yazilim-gelistirme-wiki/yazilim-gelistirme-kilavuzu/refactoring))
5. Tekrar başa dön.

### 4. Geleneksel Geliştirme vs. Testin Yönlendirdiği Geliştirme

**Geleneksel geliştirme**\
Geleneksel geliştirme alttan üste (bottom to top) bir yaklaşım sergiler. Bu tür geliştirme aşağıdaki sırayı izler:

```
Veritabanı -> Veri katmanı -> İş katmanı - Sunum katmanı
```

Beklenen davranışa odaklanılmadığından, daha ziyade implementasyon detayları üzerinden ilerlendiğinden [Y.A.G.N.I. (You're Not Gonna Need It)](https://bekoturko.gitbook.io/yazilim-gelistirme-wiki/yazilim-gelistirme-kilavuzu/refactoring/yagni) durumu yaşanması olasıdır. Genelde **fazladan kod**, fazladan test, **gereksizce karmaşık tasarım** oluşur. Bunlar da [Clean Code - Temiz Kod](https://bekoturko.gitbook.io/yazilim-gelistirme-wiki/yazilim-gelistirme-kilavuzu/clean-code) düşmanlarıdır.

**Testin yönlendirdiği geliştirme**\
Testin yönlendirdiği geliştirme ise üstten alta (top to bottom) yaklaşımı benimser. Yani işlevlerin geliştirilmesinde aşağıdaki sıra izlenir:

```
Sunum katmanı -> İş katmanı -> Veri katmanı -> Veritabanı
```

Bu yaklaşım [K.I.S.S. (Keep It Simple Stupid)](https://bekoturko.gitbook.io/yazilim-gelistirme-wiki/yazilim-gelistirme-kilavuzu/refactoring/kiss) prensibini uygulamayı sağlar. Sadece **gerektiği kadar** geliştirme yapılır, sadece gerektiği kadar test oluşur ve tasarım da buna göre basit olur.

### 5. Testin Yönlendirdiği Geliştirme Yaşam Döngüsü

![](https://2987934822-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMVhHkJTh1jcl5YdqbV%2F-MM__IXIvXWKmFMZpHny%2F-MM__SEnH26w5QLsoYCJ%2FTDD_Global_Lifecycle.png?alt=media\&token=d1b7fbde-f125-4fca-a408-9126fb8223ce)
