Test Driven Development
16 Feb 2011Merhaba,
Size kısaca bir gereklilik olan fakat genellikle hiç kullanmadığımız bir konu hakkında biraz temel bilgi vermek istiyorum: Test Driven Development
Türkçe’ye “Test Güdümlü Geliştirme” olarak çevrilmiş.
Niçin test yazmamız gerekiyor?
Geleneksel kodlamada işler şu şekildedir;
- Sınıfı (sınıf bile olmayabilir) yaz,
- Kodu deploy et,
- Hata bildirilirse hatayı bul ve kodu kendin düzelt.
Biraz daha geliştirilmiş geleneksel kodlamada ise işler şu şekildedir;
- Sınıfı yaz,
- Olası case’ler içine loglar koy,
- Kodu deploy et
- Hata bildirilirse loglara bak ve kodu düzelt.
Fakat bu geleneksel yöntemler nesne yönelimli programlama sırasında biraz canınızı sıkabilir, çünkü bu kez loglamaları koymanız gereken yer sizin sınıflarınız olacak ve her ne kadar kod tekrarını engellemiş olsanız da, tekrar kullanılabilirlik o derece aşağılara düşecektir. Yani aslında yaptığınız şey OOP değil OOP görünümlü bir yapı olacaktır. Hem stabilizasyonu artırmak hem de daha hızlı ve düzgün kod yazmak için kullanılması gereken yöntem ise TDD’dir.
İnternette TDD ile ilgili bulduğunuz dökümanları aradıktan sonra kendinize şu soruyu soruyorsunuz genellikle; “Niçin test yazayım ki, ne gereği var?” ve ardından; “Test yazacağıma kod yazarım, test yazmakla vakit harcamaktansa..” düşünceleri kafanızda dönüyor. Fakat işler tam düşündüğünüz gibi değil.
Örnek
Şimdi biraz örnekle inceleyelim; diyelim ki bir matematik sınıfımız var. Klasik dört işlemi yapabilsin, yani toplama, çıkarma, çarpma, bölme işlemleri için birer method olsun. Normalde nasıl bir sınıf yazardık?
Veya daha zekice işlemler, daha farklı implementasyonlar olabilir. TDD sizi kod yazmayı severken yazdığınız kod kadar iyi kod yazmaya yönlendiriyor.
İlk olarak test yazılmalı
Nasıl yani? Olmayan bir sınıfı mı test edeceksiniz? Evet, aynen öyle. Çünkü TDD testten geçmeniz için var olan eksiklerinizi söyleyecek, sınıf yazılması da dahil. Hani okulda sınavdan geçemediğimiz zaman öğretmenlerden hangi soruda hata yaptığımızı öğrenmek isterdik ya, diğer sınavı geçebilmek adına, mantık tamamen aynı işliyor :)
Test Sınıfı ve PHPUnit
Not: Burada sisteminize PHPUnit yüklediğinizi varsayıyorum.
Önce bomboş bir Math.php
oluşturun, daha sonra ise bir örnekteki gibi bir MathTest.php
Örnekte gördüğünüz gibi PHPUnit_Framework_TestCase
sınıfını extend eden bir MathTest
sınıfı yazdık. daha sonra buna bir setUp
bir de tearDown
methodu yazdık.
setUp
methodu, her test başlangıcında yapılacakları; tearDown
ise bitişte yapılacakları içerir. Yani her test case’inden önce Math
objesi yeniden oluşturulacak ve MathTest
objesinin object propertysini sıfırlayacak. Güzel. Zaten burada genelde pek bişey yapmazsınız. Devam edelim.
Testi hala çalıştırmıyoruz, şimdi biraz test yazalım:
Gördünüz mü, zor değil, sadece test
ile başlayan ve istediğimiz bir method adını yazıyoruz, daha sonra içerisine methoddan ne beklediğimizi yazıyoruz:
Ben sana şu parametreleri verdim, senden beklediğim ise şu;…
diyerek testimizi yazıyoruz. Burada gördüğünüz gibi toplama işlemlerimizin bize nasıl cevaplar vermesi gerektiğini önceden hazırlıyoruz, ve tüm her case’i çalışıyormuş gibi yazdıktan sonra classımız “All tests passed” diyinceye kadar çalıştırıyoruz. Ve yazdığınız bu tüm caselerden geçen sınıf en düzgün çalışan kod oluyor. Bu kadar basit. Eğer sonradan sınıfınız bir case’de çalışmazsa, suçu yazdığınız sınıfa değil teste atıyorsunuz; demek ki testi yanlış yazdınız ve bir case’i düşünmediniz.
Sonuç olarak bizim asıl beklentimiz sınıfın çalışan sistem üzerinde nasıl çalıştığı değil; testlere nasıl cevap verdiğidir.
Son bir örnekle devam edelim ve bitirelim; demin yazmış olduğum test sınıfından geçen sınıf şuydu:
Fakat testler sırasında bir olayı düşünemedik, peki ya şöyle bir case olsaydı?
O zaman demin yazdığımız methodun implementasyonu tamamen hatalıydı. Çünkü iki parametre alıyoruz ve yalnızca aldığımız iki parametreyi topluyoruz, o halde testten geçmesi için;
şeklinde görüldüğü üzere, add
methodumuzun implementasyonunu bu testi geçecek şekilde düzenliyoruz.
Son örnekte de gördüğünüz gibi, testler kodunuzu düzgün yazmanıza yardım eder ve aslında gereksiz değildir. Hatasız ve düzgün bir şekilde kodunuzu yazarsınız.
Benden temel olarak bu kadar, dahasını ve detaylı bilgileri PHPUnit veya hangi programlama dilini kullanıyorsanız onun UnitTest frameworkünü çalışarak öğrenebilirsiniz.
Kolay gelsin :)