İçeriğe geç
Muhammet Şafak
Araçlar & Teknolojiler 3 dk okuma

Laravel'de test yazma alışkanlığı: Pest'e geçiş

PHPUnit'ten Pest'e geçerken test yazmayı külfetten alışkanlığa çeviren sözdizimi ve yapı farklarını anlatıyorum.


Test yazmak iyi bir fikir olduğunu biliyordum; ama bir süre boyunca “yazmalıyım” ile “yazıyorum” arasındaki mesafeyi kapatamadım. PHPUnit’i öğrenmek zor değildi; ama her test dosyası bir sınıf, her test bir metot, $this->assertSomething() zincirleri… Sözdizimi küçük bir sürtüşme yaratıyordu ve bu sürtüşme birikince test yazmak ertelenir hale geldi.

Pest’i gördüğümde ilk tepkim “başka bir araç mı” oldu. Bir süre bekledim. Bu yılın başında ciddi bir projeye Pest ile test yazmaya başladım ve artık PHPUnit’e dönmek istemiyorum. Bu yazıda neden olduğunu anlatmaya çalışacağım.

Pest nedir

Pest (Pest PHP), Laravel ekibinin yakın çevresinden Nuno Maduro tarafından geliştirilen, PHPUnit üzerine inşa edilmiş bir test çerçevesidir (testing framework). PHPUnit’i değiştirmiyor; onun üstüne daha temiz bir sözdizimi koyuyor. Bu önemli: mevcut PHPUnit testlerinizi Pest ile çalıştırabilirsiniz, geçiş aşamalı olabiliyor.

Sözdizimi farkı

PHPUnit ile bir Feature testi:

<?php

namespace Tests\Feature;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class AuthTest extends TestCase
{
    use RefreshDatabase;

    public function test_user_can_login_with_valid_credentials(): void
    {
        $user = User::factory()->create([
            'password' => bcrypt('gizli123'),
        ]);

        $response = $this->post('/api/login', [
            'email'    => $user->email,
            'password' => 'gizli123',
        ]);

        $response->assertStatus(200)
                 ->assertJsonStructure(['token']);
    }

    public function test_user_cannot_login_with_wrong_password(): void
    {
        $user = User::factory()->create();

        $response = $this->post('/api/login', [
            'email'    => $user->email,
            'password' => 'yanlis',
        ]);

        $response->assertStatus(401);
    }
}

Aynı testler Pest ile:

<?php

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

it('kullanıcı geçerli bilgilerle giriş yapabilir', function () {
    $user = User::factory()->create([
        'password' => bcrypt('gizli123'),
    ]);

    $this->post('/api/login', [
        'email'    => $user->email,
        'password' => 'gizli123',
    ])
    ->assertStatus(200)
    ->assertJsonStructure(['token']);
});

it('kullanıcı yanlış şifreyle giriş yapamaz', function () {
    $user = User::factory()->create();

    $this->post('/api/login', [
        'email'    => $user->email,
        'password' => 'yanlis',
    ])
    ->assertStatus(401);
});

Sınıf yok, namespace yok, metot yok. it() veya test() fonksiyonu, string olarak test açıklaması, bir closure. Bu kadar.

Expectations (beklentiler) sözdizimi

Pest kendi expect() API’sini de sunuyor; assertXxx metotları yerine zincirleme kullanılabiliyor:

<?php

it('sipariş toplam fiyatı doğru hesaplanır', function () {
    $order = Order::factory()
        ->hasItems(3, ['price' => 100])
        ->create();

    expect($order->total)
        ->toBe(300)
        ->toBeGreaterThan(0);
});

expect()->toBe() okumak için çok daha doğal geliyor. Test çıktısı da aynı şekilde daha okunabilir.

Dataset ile parametre geçmek

Aynı testi farklı girdilerle çalıştırmak için PHPUnit’te dataProvider yazıyordunuz. Pest’te daha az tören:

<?php

it('geçersiz e-posta formatlarını reddeder', function (string $email) {
    $this->post('/api/register', ['email' => $email])
         ->assertStatus(422);
})->with([
    'düz metin',
    '@eksik-lokal.com',
    'eksik-@alan.com',
    'boşluk içeren@alan.com',
]);

PHPUnit’te dataProvider şöyle yazılıyordu: ayrı bir public function tanımlayacaksınız, @dataProvider docblock’u ekleyeceksiniz, metot adını eşleştireceksiniz. Pest’te .with() — hepsi bu. Sınır durumları (edge case) test etmeye teşvik eden bir ergonomi; parametreli testi yazmak kolaylaşınca daha fazla senaryo test ediyorsunuz.

Kurulum ve geçiş

composer require pestphp/pest --dev --with-all-dependencies
composer require pestphp/pest-plugin-laravel --dev
php artisan pest:install

Mevcut PHPUnit testleri dokunulmadan çalışmaya devam eder. Yeni testleri Pest ile yazmak yeterli; aşamalı geçiş mümkün.

Birlikte çalışma konusunda dikkat ettiğim bir şey: Pest’in tests/Pest.php dosyasında uses() ile belirlenen helper’lar tüm dosyalar için geçerli olabiliyor. Bu bazen beklenmedik durumlar çıkarabiliyor; örneğin bir test grubuna RefreshDatabase eklemek istiyorsanız ilgili dosyada uses(RefreshDatabase::class) yazmak, global tanımlamaya güvenmekten daha güvenli.

Yalnızca belirli bir testi çalıştırmak

Büyük bir test paketinde yalnızca üzerinde çalıştığınız testi çalıştırmak istiyorsunuz. Pest’te bunu --filter seçeneğiyle yapıyorsunuz:

php artisan test --filter "kullanıcı geçerli bilgilerle giriş yapabilir"

Ya da test dosyasını belirterek:

php artisan test tests/Feature/AuthTest.php

PHPUnit’te de bunlar mümkün ama Pest’in test açıklamaları string olduğu için --filter ile aramak daha doğal. test_user_can_login_with_valid_credentials yerine kullanıcı geçerli bilgilerle giriş yapabilir gibi Türkçe açıklamalar yazabiliyorsunuz; filtre de aynı şekilde çalışıyor.

Asıl kazanım: sürtüşme azaldı

Pest’i benimsedikten sonra fark ettiğim şey hız değildi (çalışma süresi PHPUnit ile neredeyse aynı). Asıl fark, yeni bir özellik yazdıktan sonra test açmak için duyulan direnç azaldı. Sözdizimi kısaldıkça “şunu da test edeyim” kararını vermek kolaylaştı.

Bu, araç seçiminin davranışı nasıl etkilediğine iyi bir örnek. Teknik bir fark olmasa da ergonomi üzerindeki etkisi gerçek. Test yazmayı güzel bulmak zorunda değilsiniz; ama mümkün olduğu kadar az sürtüşme yaratmasını isteyebilirsiniz.

Pest’e geçiş, test yazmayı daha sık yapmamı sağladı — ama asıl değişim alışkanlıkta oldu. Bir özelliği bitirmeden önce en az temel senaryoları yazmak bir reflekse dönüştü. Araç bunu dayatmıyor; ama kapıyı açık tutuyor. Sürtüşme azaldıkça “sonra yazarım” ertelemesi de azalıyor.

Etiketler: #Laravel#Test
Paylaş:

İlgili Yazılar

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Esc ile kapat Pagefind ile güçlendirildi