Test güdümlü geliştirme

**Test güdümlü geliştirme (TDD)**, yazılım geliştirme sürecinde gerçek kod yazılmadan önce kodun neler yapabileceğini belirleyip test vakaları geliştirerek doğrulamaların yapıldığı bu sayede süreci daha disiplinli ve sistematik hale getiren bir yaklaşımdır. Bu yöntemde, yazılım geliştirme döngüsü önce başarısız birim testlerinin yazılmasıyla başlar. Test henüz işlevsel kod olmadığı için başarısız olur ve ardından bu testi geçecek kadar kod yazılır. Daha sonra, hem test kodu hem de üretim kodu yeniden düzenlenir ve bu süreç yeni test senaryoları eklenerek tekrarlanır. TDD'nin temel amacı, kodun doğru çalıştığını baştan testlerle doğrulamak ve gereksiz kod yazmayı önleyerek kod kalitesini artırmaktır. Kısa yinelemelerle yapılan bu süreç, yazılımın güvenilirliğini artırır ve hataların erken aşamada tespit edilmesine olanak tanır.

1999 yılında  ile ortaya çıkan test öncelikli programlama kavramı, zamanla kendi başına ilgi gören bir yaklaşım haline gelmiştir. Programcılar TDD'yi yalnızca yeni projelerde değil, aynı zamanda eski kodların iyileştirilmesi ve hataların ayıklanması için de kullanmaktadır.

## Tarihçesi
Kent Beck, Aşırı Programlama (XP) çerçevesinde Test Güdümlü Geliştirme (TDD) tekniğini geliştirmiştir. Beck, TDD'nin basit ve etkili tasarımlar oluşturmayı teşvik ettiğini ve yazılımcılara güven sunduğunu belirtmiştir. Ayrıca, TDD'nin orijinal tanımı eski bir programlama kitabında geçen bir ifadeye dayanmaktadır: "Girdi bandını alırsınız, beklediğiniz çıktı bandını elle yazarsınız; ardından gerçek çıktı bandı, beklenen çıktı ile eşleşene kadar programlama yaparsınız." Beck Smalltalk'taki ilk xUnit çerçevesini yazdıktan sonra bu bilgiyi okuduğunu hatırladığını ve denediğini belirterek, bu deneyimin onun için TDD'nin başlangıcı olduğunu vurgulamıştır. Beck, TDD'yi “yeniden keşfetmek” olarak adlandırarak, bu yöntemin daha önce var olduğunu ancak sistematik bir şekilde uygulanmadığını ifade etmiştir.

1998 yılında XP (Aşırı Programlama) metodolojisi çerçevesinde "testleri çoğunlukla ilk sırada yazmalıyız" diyerek Test First kavramını geliştirmiştir. 2002 yılında yayımladığı *Test Driven Development: By Example* adlı eserinde bu yaklaşımı daha derinlemesine incelemiştir. Bu çalışma, yazılımcılar arasında büyük yankı uyandırmış ve TDD'nin yazılım geliştirme süreçlerinde önemli bir yer edinmesini sağlamıştır. Aradan geçen yıllara rağmen TDD, halen yazılım geliştirme alanında önemli bir kaynak ve rehber olarak değerlendirilmektedir.

## Kodlama Döngüsü
TDD, kullanıcı hikâyelerine dayalı olarak ilerleyen bir süreçtir ve küçük bir görevle başlayıp bu görev için testler yazarak devam eder. Belirli adımlar izleyerek yazılım geliştirme sürecini yapılandırır. Test Güdümlü Geliştirme (TDD) süreci aşağıdaki aşamalarla gerçekleştirilir:

**1.Yeni bir özellik eklenirken, önce senaryolar belirlenmelidir**

İlk adımda, kullanıcı hikâyesine dayanan bir görevin veya geliştirilecek olan fonksiyonun seçilerek beklenen değişkenleri listeleyin.

**2.Liste hazırlandıktan sonra, ilk aşama olarak bu maddelerden biri için test yazılır**

Değişkenleri test edecek bir test yazın.

**3.Testleri çalıştırın**

Tüm testler çalıştırıldığında yeni yazılan testin bu aşamada başarısız olması beklenir çünkü bu, yeni özellik için kodun gerçekten gerekli olduğunu kanıtlar. Ayrıca, test koşumunun doğru çalıştığını ve testin yanlış bir şekilde her zaman geçmeyeceğini doğrular.

**4.Yeni testi geçecek basit bir kod yazın**

Testi geçmek için gereken kod yazılır. Bu aşamada kodun mükemmel olmasına gerek yoktur; önemli olan sadece testin başarılı olmasını sağlayacak işlevselliğin eklenmesidir. Yazılan kod, sonraki adımlarda iyileştirilecektir bu nedenle başka hiçbir kod eklenmemelidir.

**5.Bütün testleri yeniden çalıştırın**

Kodun yazılmasının ardından, tüm testler yeniden çalıştırılır ve yeni yazılan kodun hem mevcut hem de yeni testleri geçip geçmediği kontrol edilir. Bu aşamada yazılan tüm testler başarılı olmalıdır. Eğer bir test başarısız olursa, en az düzeltmeyle hatalar giderilir.

**6.Kodu yeniden düzenleyin**

Testler başarıyla tamamlandıktan sonra, kodun düzenlenmesi ve iyileştirilmesi için "refactoring" adı verilen bir aşamaya geçilir. Bu adımlar, her yeni test senaryosu ile tekrarlanarak yazılımın kalitesini artırır. Bu aşamada kodun okunabilirliğini artırmak için yeniden düzenlenir. Özellikle sabit kodlanmış test verileri üretim kodundan kaldırılmalıdır. Her yeniden yapılandırma işleminin ardından, mevcut işlevselliği korumak için test paketi çalıştırılmalıdır.

**Tekrarla**

Bu süreç, yeni bir test yazılarak ve yukarıdaki adımlar tekrarlanarak devam eder. Her yeni fonksiyon için döngü baştan başlar. Bu döngü, her yeni özelliğin adım adım, test odaklı bir yaklaşımla geliştirilmesini sağlar.

## TDD için Kullanılan Yazılım ve Araçlar
Test Güdümlü Geliştirme (TDD) sürecinde kullanılan birçok test çerçevesi ve araç, yazılımcıların test senaryolarını oluşturmasını ve bu testleri otomatik olarak çalıştırmasını sağlar.

**xUnit Çerçeveleri**

Test Güdümlü Geliştirme (TDD) için geliştiriciler, test senaryolarını yazmak ve bu testleri otomatik olarak çalıştırmak için genellikle xUnit olarak adlandırılan test çerçevelerini kullanır. Bu çerçeveler, 1998'de oluşturulan SUnit'ten türetilmiştir. xUnit ailesi, yazılım projelerinde yaygın olarak kullanılan test çerçevelerini içerir ve assertion tabanlı test doğrulama yetenekleri ile sonuç raporlama sağlar. Bu yetenekler, geliştiricilere kodun doğru çalışıp çalışmadığını kontrol etme ve hataları yakalama imkanı sunar. Böylece testleri manuel olarak kontrol etmek yerine otomatik hale getirir ve test sürecini hızlandırır.

Bu çerçeveler tarafından sağlanan yürütme altyapısı, tüm sistem test senaryolarının veya belirli alt kümelerin otomatik olarak çalıştırılmasına olanak tanır. Bu sayede yazılımın farklı bileşenlerinin, test senaryolarına uygun çalışıp çalışmadığı hızlı bir şekilde doğrulanabilir.

**TAP Sonuçları**

Bazı test çerçeveleri, **Test Anything Protocol** (TAP) adında dil bağımsız bir protokol aracılığıyla birim test çıktısını kabul edebilir. TAP, 1987 yılında oluşturulmuştur ve test sonuçlarını standart bir formatta sunarak farklı dillerde ve ortamlarda birim testlerin sonucunu evrensel bir dilde raporlamayı mümkün kılar.

**JUnit (Java)**

JUnit, Java programlama dili için geliştirilmiş bir test çerçevesidir. Unit testlerini yazmak, çalıştırmak ve yönetmek için kullanılır. JUnit, testlerin sistematik bir şekilde yazılmasını ve sürekli entegrasyon süreçlerinde otomatik olarak çalıştırılmasını kolaylaştırır. Anotasyonlar kullanarak test durumları ve test grupları tanımlamaya olanak tanır.

**NUnit (.NET/C#)**

NUnit, .NET platformu için geliştirilmiş bir test çerçevesidir. C# ile yazılan uygulamalardaki birim testlerini oluşturmak için kullanılır. NUnit, test metotlarını tanımlamak için çeşitli anotasyonlar sağlar ve testlerin organize edilmesini, çalıştırılmasını ve raporlanmasını kolaylaştırır.

**PyTest (Python)**

PyTest, Python için oldukça popüler ve esnek bir test çerçevesidir. Test yazımını basit hale getiren bir yapıya sahiptir ve karmaşık test senaryolarını kolayca yönetebilir. Ayrıca, çok sayıda eklenti desteği ile genişletilebilir.

## Test Güdümlü Geliştirmenin Avantajları ve Dezavantajları
**Avantajları**

Test Güdümlü Geliştirme (TDD), yazılım geliştirme sürecinde testlerin gerçek koddan önce yazıldığı bir yaklaşımdır. Bu yöntem, geliştiricilere çeşitli avantajlar sunar:

**1. Kapsamlı Test Kapsamı**: TDD, tüm yeni kodların en az bir test kapsamına alınmasını sağlayarak daha sağlam yazılımlar ortaya çıkarır.

**2.Kodda Geliştirilmiş Güven**: Geliştiriciler kodun güvenilirliği ve işlevselliği konusunda daha fazla güven kazanırlar.

**3.İyi Belgelenmiş Kod**: TDD, her testin kodun amacını açıkça ortaya koymasını sağlar. Bu da doğal olarak daha iyi belgelenmiş ve anlaşılır bir kod tabanı oluşturur.

**4.Gereksinim Netliği**: TDD, kodlama başlamadan önce gereksinimlerin net bir şekilde anlaşılmasını teşvik eder.

**5.Sürekli Entegrasyonu Kolaylaştırır**: Sürekli entegrasyon süreçleriyle iyi entegre olur, sık kod güncellemelerine ve testlere olanak tanır.

**6.Üretkenliği Artırır**: Birçok geliştirici TDD'nin üretkenliklerini artırdığını düşünüyor.

**7.Kod Zihinsel Modelini Güçlendirir**: TDD, kodun yapısı ve davranışına ilişkin güçlü bir zihinsel model oluşturulmasına yardımcı olur.

**8.Tasarım ve İşlevselliğe Vurgu Yapar**: Programın tasarımına, ara yüzüne ve genel işlevselliğine odaklanmayı teşvik eder.

**9.Hata Ayıklama İhtiyacını Azaltır**: TDD, sorunları geliştirme sürecinin erken aşamalarında yakalayarak daha sonra kapsamlı hata ayıklama ihtiyacını azaltır.

**10.Sistem Kararlılığı**: TDD ile geliştirilen uygulamalar daha kararlı ve hatalara daha az eğilimli olma eğilimindedir.

**Dezavantajları**

Ancak TDD'nin dezavantajları da bulunmaktadır:

**1.Artan Kod Hacmi**: TDD uygulandığı zaman, yazılan testler toplam kod miktarına eklendiğinde daha büyük bir kod tabanına neden olabilir.

**2.Testlerden Kaynaklanan Yanlış Güvenlik**: Çok sayıda başarılı test bazen kodun sağlamlığı konusunda yanıltıcı bir güvenlik hissi verebilir.

**3.Bakım Ek Yükleri**: Geniş bir test paketinin bakımı, geliştirme sürecine ek yük getirebilir

**4.Zaman Alan Test Süreçleri**: Testlerin yazılması ve sürdürülmesi zaman alıcı olabilir. Bu nedenle proje gelişim süresinin uzamasına neden olabilir.

**5.Test Ortamı Kurulumu**: TDD, uygun bir test ortamının kurulmasını ve sürdürülmesini gerektirir.

**6.Öğrenme Eğrisi**: TDD uygulamalarında yetkinleşmek zaman ve çaba gerektirir.

**7.Aşırı Karmaşıklık**: TDD'ye aşırı vurgu yapılması, kodun gereğinden fazla karmaşık olmasına yol açabilir

**8.Genel Tasarımın İhmali**: Testleri geçmeye çok dar bir şekilde odaklanmak bazen yazılım tasarımındaki büyük resmin ihmal edilmesine yol açabilir.

**9.Artan Maliyetler**: TDD için gereken ek zaman ve kaynaklar daha yüksek geliştirme maliyetlerine neden olabilir.

Test Güdümlü Geliştirme (TDD) yazılım geliştirmede değerli bir uygulamadır ve iyileştirilmiş kod kalitesi ve sürdürülebilirlik gibi uzun vadeli faydalar sunmaktadır. TDD kullanarak daha fazla test yazılır ancak bu, programcıların üretkenliğini artırabilir. TDD, kodun doğruluğunu sadece test etmekle kalmaz, aynı zamanda yazılım tasarımını da yönlendirir ve geliştiricileri öncelikle kullanıcı ara yüzüne odaklanmaya teşvik eder. Küçük adımlarla ilerleme imkanı sunar ve hata durumları başlangıçta dikkate alınmasa bile daha sonra ayrı testlerle ele alınır. Ek olarak, TDD testlerin kapsamını genişletir ve beklenmeyen davranış değişikliklerini daha kolay tespit etmeye yardımcı olur.

## Kaynakça