Başlarken
Önceki yazılarımda Test Driven Development hakkında bir giriş yapmıştık. Tabiki gerçek hayatta $this->assertTrue(true)
yapmıyoruz 🙂 Şimdiki yazımda ise gerçek hayatta birim testler nasıl uygulanıyor onlar hakkında konuşacağım. Daha önceki yazılarıma ulaşmak isterseniz:
Test Driven Development (TDD) Nedir?
Birim Nedir?
Birim test yapmadan önce birimin ne olduğunu bilmek şart 🙂
Birim: Bir yazılımın test edilebilir en küçük parçasıdır. Bu OOP’ta genelde bir method olarak nitelendirilir.
Özellikleri
Birim testlerin en önemli özelliği bir test’in dışarı bağımlı olmamasıdır. Eğerki blog uygulamanızdaki Post
classını test ediyorsanız bunu veritabanına bağlanmadan test etmelisiniz.
Peki veritabanına düzgün ekliyor mu nasıl anlayacağız?
Merak etme onun da kendi testi var.
Benim uygulamam veritabansız çalışmaz ki???
İşte bu yüzden Test Edilebilir Kod Üretmek konusunda konuşmuştuk. Şimdi ise bu ürettiğimiz test edilebilir kodları nasıl test edeceğiz onlar hakkında konuşacağız.
Mock Objects
İşte burası zurnanın zırt dediği yer. Mock objesi sahte/taklit obje anlamına geliyor. Yani siz Post
sınıfınızı veritabansız test edecekseniz o veritabanı sınıfının sahtesini yazacaksınız (taklit edeceksiniz) ki bu sınıfta veritabanı kullanmayacak. Yani veritabanı sınıfını simule edeceğiz. Örnekle şekillendirelim
interface PostInterface {
public function yarat($user_id, $baslik, $icerik);
}
class Post_MySQL implements PostInterface {
public function yarat($user_id, $baslik, $icerik) {
$stmt = DB::getConnection()->prepare('INSERT INTO post VALUES (?,?,?)');
return $stmt->execute(array($user_id, $baslik, $icerik));
}
}
Örnekte veritabanı aracılığı ile bloga girilen postu kaydeden bir model sınıfımız var. Şimdi ise bu model’i kullanan bir Controller yazıyorum:
class PostController {
private $post;
public function __construct(PostInterface $post) {
$this->post = $post;
}
public function yarat() {
$sonuc = $this->post->yarat($_POST['user_id'], $_POST['baslik'], $_POST['icerik']);
if ($sonuc == true) {
return "Post başarıyla yaratıldı";
} else {
return "Beklenmeyen hata oluştu";
}
}
}
Asıl yaratma işleminin yapılacağı sayfada ise şu şekilde controller’ımı kullanıyorum:
$controller = new PostController(new Post_MySQL());
echo $controller->yarat();
Mock Objelerinin yaratılması ve kullanılması
Mock objeleri aslında çok basit bir şekilde yaratılır. Siz zaten kodunuzu test edilebilir bir şekilde hazırladığınız için bu sizin için bir sorun olmayacak 🙂 Şimdi iki tane hazırlıyorum.
class BasariliYaratma implements PostInterface {
public function yarat($user_id, $baslik, $icerik) {
return true;
}
}
class BasarisizYaratma implements PostInterface {
public function yarat($user_id, $baslik, $icerik) {
return false;
}
}
İşte bu kadar basit! Şimdi ise testimi hazırlayabilirim:
class PostTest extends PHPUnit_Framework_TestCase {
public function testPostBasariylaEklendigindePostBasariylaYaratildiYazisiGeliyor() {
// dependency injection
$controller = new PostController(new BasariliYaratma());
$this->assertEquals("Post başarıyla yaratıldı", $controller->yarat());
}
public function testVeritabaniBaglantisiIleIlgiliSikintiOldugundaHataMesajiGoster() {
// dependency injection
$controller = new PostController(new BasarisizYaratma());
$this->assertEquals("Beklenmeyen hata oluştu", $controller->yarat());
}
}
Daha sonra testlerimizi çalıştırıyoruz ve controller’ımızın beklenen adımları gerçekten sergileyip sergilemediğine bakıyoruz.
Sonuç
Sonuç olarak basit bir şekilde mock objelerinin nasıl yaratılacağını görmüş olduk. Ancak gerçek hayatta 10larca hatta 100lerce sınıfınız olabilir o yüzden 1000lerce mock objesine ihtiyaç duyabilirsiniz. Biz gerçek hayatta, bunları amele gibi tek tek oluşturmuyoruz. Bunun için PHPUnit’in getMock
method’u veya Mockery sınıfı kullanılıyor. Bir sonraki yazımda Mockery aracı ile nasıl mock objeleri yaratıldığı hakkında konuşacağım. Hadi kolay gelsin.