Unit testing ve PHPUnit

Kadir Doğuş Seçkin
3 min readSep 23, 2023

--

Unit test nedir ?

Unit testing kodu ayırabildiğimiz en küçük parçalara ayırıp, her bir parçasını test etmemizin bir yoludur. Bu en küçük parçalar genellikle fonksiyonlar olur.

Neden unit test yazarız ?

Unit test yazmanın bir çok avantajı vardır. Öncelikle geliştirdiğimiz yazılımdaki hataları bulmamamızı kolaylaştırır ve onları tekrar yapmamızı engeller.

Projemiz için yeni bir özellik geliştirdiğimizi düşünelim. Bu özellik için 5 farklı senaryo olsun. Eğer biz her geliştirdiğimiz senaryo için bu kodun unit testini de yazarsak hem o senaryonun istenildiği gibi çalışıp çalışmadığını görürüz. Hem de daha sonraki senaryoları eklerken ilk yazdığımız kodda bir hataya neden olursak bunu direkt ilk yazdığımız unit testte yakalayabiliriz. Bu da kodu daha özgüvenle yazmamızı sağlar.

Projeyi geliştirirken unit testlerini yazmak projenin geliştirme süresini uzatan bir faktördür. Bazıları için bu zaman kaybı olarak görülür ama öyle düşünülmemelidir. Çünkü yukarıda bahsettiğim sebeplerden dolayı unit test uzun vadede bize çok zaman kazandırır ve hata oluşmasını engeller.

Çok uzun süre önce geliştirilen, bir çok yazılımcının üzerinde çalıştığı ve bir çok özellik eklenen bir yapıda unit testlerin olması o projeye sonradan dahil olan yazılımcıların hatta o proje üzerinde kod yazmış yazılımcıların orada kod yazarken daha önce var olan sistemde bir hataya sebep olmadan yeni özellikler ekleyebilmesine olanak sağlar.

Unit testler aynı zamanda kodun neler yaptığını anlamamıza olanak sağlar. Tüm testlerin yazıldığı bir proje dökümante edilmek istenirse unit testleri inceleyip bu işi yapmak süreci epey kolaylaştıracaktır.

Unit test yazmak için farklı frameworklerin bize sunduğu bir çok yapı vardır. Ben burada PHPUnit’i anlatacağım. PHPUnit, PHP projeleri üzerinde unit test yazmamıza olanak sağlar.

Aşağıdaki terminal komutunu çalıştırarak composer yardımıyla projemize PHPUnit’i dahil edebiliriz.

composer require phpunit/phpunit

Unit test sınıflarımız PHPUnit’in TestCase sınıfından türemelidir.

class CustomerTest extends TestCase {}

Sınıfımızın içinde test fonksiyonlarının algılanabilmesi için 2 yöntem vardır. Fonksiyon isimlerimizi test kelimesiyle başlatabiliriz ya da fonksiyonların üstünde annotation kullanabiliriz. İkisinden birini kullanmak yeterli olacaktır.

 /**
* @test
**/
public function testGetCustomer()
{
$mCustomer = new Customer();
$actualCustomer = $mCustomer->getCustomer();
$expectedCustomer = [
'id' => 1,
'name' => 'Name',
'email' => 'email@test.com'
];
$this->assertEquals($expectedCustomer,$actualCustomer);
}

Testler içinde kontrollerin sağlanması için assert fonksiyonları kullanılır. Yukarıdaki test getCustomer fonksiyonuna gidip kullanıcı bilgisini alıyor. Ardından assertEqual fonksiyonu ile gelen kullanıcı verisinin istenilen veriyle aynı olup olmadığını kontrol ediyor. PHPUnit içinde bunun gibi bir çok assert fonksiyonu vardır ve bunlar sayesinde çeşitli kontroller yapabiliriz.

Eğer her fonksiyonumuz için ortak çalışacak yapılarımız varsa bunlar için TestCase sınıfından kalıtımla gelen setUp ve tearDown fonksiyonlarını kullanabiliriz.

 protected function setUp(): void
{

}

protected function tearDown(): void
{

}

Bazen de testlerimizde mocklamaya ihtiyaç duyabiliriz. Mock objelerimizin, fonksiyonlarımızın davranışlarını değiştirmemize olanak sağlayan bir yapıdır. Bu sayede bağımlılıkları olan bir yapıyı , bağımlılıklarından izole bir şekilde test edebiliriz.

Tekrar getCustomer fonksiyonumuzu düşünelim. Bu sefer bu fonksiyonun kullanıcı datasını dönmesi için kendi içinde isVerified kontrolü yaptığını varsayalım. Biz ise isVerified true olan senaryoları test etmek isteyelim. Fonksiyonun o kısmını mocklayıp her zaman true dönüyormuş gibi davranmasını sağlayabiliriz. Bu senaryoya göre de fonksiyonun diğer kısımlarını test edebiliriz.

    public function testGetCustomer()
{
$mockCustomer = $this->getMockBuilder(Customer::class)
->setMethods(['isVerified'])
->getMock();

$mockCustomer->method('isVerified')->willReturn(true);

$actualCustomer = $mockCustomer->getCustomer();
$expectedCustomer = [
'id' => 1,
'name' => 'Name',
'email' => 'email@test.com'
];

$this->assertEquals($expectedCustomer, $actualCustomer);
}

--

--