Laravel ile AI Özelliklerini Test Etme Rehberi
AI özelliklerini test etmenin pahalı kısmı API maliyetleri değildir. Asıl sorun, yanlış güven duygusudur. Laravel testleriniz yalnızca bir kontrolcünün 200 döndüğünü kanıtlarsa, AI davranışını test etmiyorsunuz. Gerçekten, uygulamanızın bir ağ isteği yapabildiğini test ediyorsunuz.
Modeli Bir Harici Bağımlılık Olarak Ele Alın
Eğer kontrolcünüz, işiniz veya Livewire bileşeniniz OpenAI ile doğrudan iletişim kuruyorsa, testleriniz hızla kırılgan hale gelir. Nakliye tüm detaylarına bağlı şekilde ürünü test etmekle kalırsınız.
Daha iyi bir yöntem, AI entegrasyonunuzu tek bir uygulama servisi arkasına yerleştirmektir. Bu servis, AiReply, DraftResult veya SupportAnswer gibi küçük, uygulamaya özgü bir sonuç nesnesi döndürebilir. Kontrolcüleriniz uygulama davranışını test eder. Sağlayıcı entegrasyonu daha dar bir test kümesine tabi tutulur.
Bu sınır önemlidir, çünkü sahte verileriniz sözleşmenizi yansıtmalıdır, sağlayıcının tüm yükünü değil. Sağlayıcılar alanları değiştirir. Uygulamanız bu değişiklikten etkilenmediği sürece umursamamalıdır.
Örnek:
namespace App\Services\Ai;
final class ProductCopyService
{
public function __construct(private OpenAiResponsesClient $client) {}
public function generate(string $name, string $audience): ProductCopyResult
{
$response = $this->client->create([
'model' => 'gpt-5.4',
'input' => "Write concise product copy for {$name} aimed at {$audience}.",
]);
return new ProductCopyResult(
headline: data_get($response, 'output_text', ''),
tokensUsed: (int) data_get($response, 'usage.total_tokens', 0),
);
}
}
Artık uygulama testleriniz tüm sağlayıcı alanlarını bilmek zorunda değildir. Sadece geçerli bir ProductCopyResult’ın nasıl göründüğünü bilmelidirler.
Sahte Model Yanıtlarını Kullanma
Pek çok ekip erken durarak bir 200 OK ve birkaç metin kullanarak işi bitiriyor. Bu sadece modelin tam olarak beklediğiniz gibi davrandığı mutlu yolu kapsar.
İhtiyacınız olan en az üç sınıf sahte yanıt:
- Uygulamanızın kabul etmesi gereken geçerli bir yanıt.
- Uygulamanızın reddedeceği veya normalleştireceği yapısal olarak geçerli bir yanıt.
- Uygulamanızın düzgün bir şekilde işlemesi gereken bir sağlayıcı hatası.
HTTP Entegrasyonları için:
use Illuminate\Support\Facades\Http;
use function Pest\Laravel\postJson;
it('stores generated copy without calling the real API', function () {
Http::fake([
'api.openai.com/*' => Http::response([
'output_text' => 'Ship faster with a Laravel-first AI workflow.',
'usage' => ['total_tokens' => 148],
], 200),
]);
$response = postJson('/products/copy', [
'name' => 'QCode Deploy',
'audience' => 'Laravel teams',
]);
$response
->assertOk()
->assertJsonPath('headline', 'Ship faster with a Laravel-first AI workflow.');
Http::assertSent(function ($request) {
return str($request->url())->contains('/v1/responses')
&& $request['model'] === 'gpt-5.4';
});
});
Yanlış Yapılandırılmış Çıktıları Test Edin
AI hataları genelde çökmeler değildir. Genellikle oldukça makul görünen yanlış çıktılardır. Örnekler:
- Markdown sınırları içinde dönen JSON.
- Yapısal bir yük içerisindeki eksik alanlar.
- Sözdizimsel olarak geçerli fakat anlamsal olarak yanlış olan argümanlar.
Bunlar, üretim temizlik işlerinden sizi kurtaran testlerdir.
it('rejects product copy when the model returns empty content', function () {
Http::fake([
'api.openai.com/*' => Http::response([
'output_text' => '',
'usage' => ['total_tokens' => 83],
], 200),
]);
$response = postJson('/products/copy', [
'name' => 'QCode Deploy',
'audience' => 'Laravel teams',
]);
$response
->assertStatus(422)
->assertJsonPath('message', 'AI returned an unusable result.');
});
Ayrıntılı Hata Durumlarını Zorlayın
Model belirli bir aracı çağırırsa, basit testler yıkılmaya başlar. Bir çıkış kümesi yerine, bir mini iş akışı testi yapıyorsunuz. Bu detay önemlidir çünkü kötü ilişkileri test etmek kolaydır.
Doğru Asserts:
- Aracın yalnızca bir kez çağrıldığını doğrulamak.
- Parçalanmış argümanların beklenen şemaya uyduğunu test etmek.
- Son kullanıcı yanıtının, hayal ürünü veriler değil, araç çıktısına göre yansıtılması.
it('executes the stock lookup tool and returns the final answer', function () {
Http::fakeSequence()
->push([
'output' => [[
'type' => 'function_call',
'call_id' => 'call_123',
'name' => 'lookupInventory',
'arguments' => json_encode(['sku' => 'QC-DEPLOY']),
]],
], 200)
->push([
'output_text' => 'QCode Deploy is in stock and ships this week.',
], 200);
$tool = Mockery::mock(InventoryLookup::class);
$tool->shouldReceive('forSku')
->once()
->with('QC-DEPLOY')
->andReturn(['in_stock' => true, 'eta' => 'this week']);
$this->app->instance(InventoryLookup::class, $tool);
$response = $this->postJson('/support/ask', [
'question' => 'Can I get QCode Deploy this week?',
]);
$response
->assertOk()
->assertJsonPath('answer', 'QCode Deploy is in stock and ships this week.');
});
Yaygın Hata Durumları Oluşturun
Model, artık mevcut olmayan bir aracı talep edebilir veya gerekli anahtarları olmayan argümanlar ile başlayabilir. Bu tür hataları test etmemişseniz, AI özelliğiniz hala bir demodur.
Kesinti Testlerinde:
it('falls back gracefully when the provider times out', function () {
Http::fake(function () {
throw new ConnectionException('Timed out contacting AI provider.');
});
$response = $this->postJson('/support/ask', [
'question' => 'Summarize this order issue',
]);
$response
->assertStatus(503)
->assertJsonPath('message', 'AI is temporarily unavailable.');
});
Aİ Davranışını Gözden Geçirin
Aİ değişikliklerini gözden geçirmek, mühendislik kalitesini artırır. Uygulama testlerinizi belirli bir sınırda tutarak, gerçek sağlayıcı çağrılarınızı nadir hale getirerek, güvenilirliği artırabilirsiniz.
Testlere Dikkat Edin:
- Yalnızca normalleştirilmiş çıktılara dayanarak test edin.
- Snapshot alırken yalnızca kendi DTO’nuzu veya kırpılmış JSON şeklini alın, ham yükleri değil.
- Sadece bir veya iki canlı entegrasyon testi yapmaya özen gösterin, bu da oturum açma, model eskime veya yarı bozuk istek biçimini yakalamak için yeterli olacaktır.
Sıfır kredilendirme ve neredeyse sıfır rastgelelik ile günlük test setinize odaklanın. Bu, unit ve feature test kategorilerinin AI işleyişini deterministik bir şekilde daima koruduğunu, gerçek API çağrılarının ise yalnızca doğrulama olarak kalması gerektiğini belirten bir kuraldır.
Laravel AI testleriniz hala canlı bir model üzerine bağımlıysa anlamlı görünmek için, probleminiz bütçede değil. Probleminiz sınırın çok gevşek olmasıdır.
Sınırı sıkılaştırın, doğru katmanları sahteleyin ve öncelikle zor durumları test edin. AI özelliklerinizi API kredilerini veya güveninizi zarar vermeden gönderin.
Kaynak: Orijinal Makale


