Entegrasyon ve İşlevsel Test
Bileşenlerin gerçekte birlikte nasıl çalıştığını test edin.
Entegrasyon ve İşlevsel Test, CoddyKit'te ücretsiz bir PHP Academy dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, PHP Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. PHP Academy kursu toplamda 4 dersten oluşur.
Birim Sınamasının Ötesi
Birim sınamaları, her şeyin sahte nesnelerle taklit edildiği bir sınıfın yalıtılmış olarak çalıştığını kanıtlar. Ancak sahte nesneler yanıltabilir — gerçek veritabanı, çerçeve yönlendiricisi veya HTTP katmanı farklı davranır. Tümleştirme sınamaları, birbirine bağlanmış iki veya daha fazla gerçek bileşeni doğrular; işlevsel sınamalar, uygulamayı herkese açık giriş noktası (HTTP isteği, konsol komutu) üzerinden uçtan uca çalıştırır. Bu derste her iki türün yeri belirlenip yazımı gösterilecektir.
Sınama Piramidi
Sağlıklı bir sınama paketi piramit şeklindedir:
- Çok sayıda birim sınaması — hızlıdır, yalıtılmıştır ve sürekli çalıştırılır.
- Daha az sayıda tümleştirme sınaması — gerçek veritabanı/kuyruk/önbellek kullanır ve daha yavaştır.
- Az sayıda işlevsel/uçtan uca sınama — tüm yığını kullanır, en yavaştır ve en kırılgandır.
Bunu tersine çevirmek (çoğunlukla uçtan uca sınamalardan oluşan bir “dondurma külahı” oluşturmak) yavaş ve kararsız bir sınama paketi ortaya çıkarır. Mümkün olduğunda kapsama ağırlığını alt katmanlara kaydırın.
Tümleştirme: Veri Deposunu Gerçek Veritabanıyla Sınama
Bir veri deposu için tümleştirme sınaması, SQL, şema ve eşleme hatalarını yakalamak üzere sahte nesne yerine gerçek bir veritabanı bağlantısı kullanır. Özel bir sınama veritabanı (veya SQL lehçenizle yeterince örtüşen bellek içi bir SQLite) ve gerçek bir PDO kullanın.
<?php
use PHPUnit\Framework\TestCase;
final class UserRepositoryTest extends TestCase
{
private \PDO $pdo;
protected function setUp(): void
{
$this->pdo = new \PDO('sqlite::memory:');
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$this->pdo->exec('CREATE TABLE users (id INTEGER PRIMARY KEY, email TEXT)');
}
public function test_persists_and_finds_a_user(): void
{
$repo = new UserRepository($this->pdo);
$id = $repo->create('ada@example.com');
self::assertSame('ada@example.com', $repo->find($id)->email);
}
}
Yalıtım: İşlem Geri Alma
Tümleştirme sınamaları birbirlerinin durumunu sızdırmamalıdır. En hızlı yöntem, her sınamayı bir işlem içine almak ve tearDown() içinde geri almaktır — veritabanı yeniden veri ekmeye gerek kalmadan temiz duruma döner. (Sınanan kod işlemi kesinleştiriyor veya DDL kullanıyorsa tabloları boşaltmak yedek seçenektir.)
<?php
protected function setUp(): void
{
$this->pdo = TestDb::connection();
$this->pdo->beginTransaction();
}
protected function tearDown(): void
{
$this->pdo->rollBack(); // undo everything this test did
}
Veri Örnekleri ve Üreticiler
Sınamaların veriye ihtiyacı vardır. Kırılgan, devasa SQL dökümlerinden kaçının; bunun yerine yalnızca sınamanın ihtiyaç duyduğu satırları oluşturan ve her durum için üzerine yazabileceğiniz mantıklı varsayılanlara sahip küçük üreticileri tercih edin. Böylece her sınamanın amacı açık kalır ve şema büyümesine karşı dayanıklı olur.
<?php
final class UserFactory
{
public static function create(\PDO $pdo, array $overrides = []): int
{
$data = array_merge(['email' => 'user'.uniqid().'@test.dev'], $overrides);
$stmt = $pdo->prepare('INSERT INTO users (email) VALUES (:email)');
$stmt->execute($data);
return (int) $pdo->lastInsertId();
}
}
İşlevsel: Uygulamaya İstemci Gibi İstek Gönderme
İşlevsel sınama, benzetilmiş bir istekle gerçek uygulama çekirdeğini/yönlendiricisini çalıştırır ve yanıtın durum kodu, üstbilgileri ve gövdesi üzerinde doğrulama yapar. Symfony'nin WebTestCase sınıfı ve Laravel'in HTTP sınama yardımcıları, gerçek bir web sunucusu başlatmadan tam olarak bunu yapar. Aşağıda Symfony biçimi gösterilmektedir.
<?php
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
final class HealthControllerTest extends WebTestCase
{
public function test_health_endpoint_returns_ok(): void
{
$client = static::createClient();
$client->request('GET', '/health');
self::assertResponseIsSuccessful(); // 2xx
self::assertJson($client->getResponse()->getContent());
}
}
Yanıtı Doğrulama
İşlevsel sınamalar, sınırdaki gözlemlenebilir davranışı doğrular: durum, JSON yapısı ve veritabanındaki yan etkiler. Aşağıda bir POST bir kaynak oluşturuyor; hem HTTP yanıtını hem de kaydın gerçekten depolamaya yazıldığını denetliyoruz — böylece tüm yığının birlikte çalıştığını kanıtlıyoruz.
<?php
public function test_creating_a_user_persists_it(): void
{
$client = static::createClient();
$client->request('POST', '/users', server: [
'CONTENT_TYPE' => 'application/json',
], content: json_encode(['email' => 'ada@example.com']));
self::assertResponseStatusCodeSame(201);
$repo = static::getContainer()->get(UserRepository::class);
self::assertNotNull($repo->findByEmail('ada@example.com'));
}
Dış Bağımlılıkları Seçici Olarak Sahteleme
İşlevsel sınamalar bile gerçek ödeme sağlayıcılarını çağırmamalı veya gerçek e-postalar göndermemelidir. Yalnızca en dıştaki harici hizmetleri değiştirin — sınama kapsayıcısında bunları sahte/bellek içi uygulamalarla değiştirin — kendi kodunuzu, yönlendirmenizi ve veritabanınızı gerçek tutun. Böylece kararsız ağ çağrıları olmadan uçtan uca gerçeğe yakınlık korunur.
<?php
public function test_checkout_charges_via_gateway(): void
{
$client = static::createClient();
// Replace the real gateway binding with an in-memory fake:
static::getContainer()->set(PaymentGateway::class, new FakePaymentGateway());
$client->request('POST', '/checkout', content: json_encode(['cart' => 1]));
self::assertResponseIsSuccessful();
}
Ayrı Sınama Kümeleri, Ayrı Hızlar
phpunit.xml dosyanızı sınama kümelerine ayırın; böylece hızlı birim sınama kümesi her kaydetmede çalışırken yavaş tümleştirme/işlevsel kümeler isteğe bağlı olarak veya CI içinde çalışır. Dizinlere göre gruplayın ve --testsuite ile seçim yapın.
<phpunit>
<testsuites>
<testsuite name="unit">
<directory>tests/Unit</directory>
</testsuite>
<testsuite name="integration">
<directory>tests/Integration</directory>
</testsuite>
<testsuite name="functional">
<directory>tests/Functional</directory>
</testsuite>
</testsuites>
</phpunit>Kapsamadan Önce Belirlenimlilik
Bir sınama paketine duyulan güveni kaybetmenin en hızlı yolu kararsızlıktır. Tümleştirme/işlevsel sınamaları belirlenimli hâle getirin:
time()çağırmak yerine zamanı dondurun (bir saat sağlayıcısı enjekte edin).- Rastgeleliği tohumlayın; sıralanmamış sorgularda sıraya bağlı doğrulamalardan kaçının.
- Her sınamada veritabanı durumunu sıfırlayın (işlem geri alma / tabloları boşaltma).
- Sınamaların çalıştırılma sırasına asla güvenmeyin.
Sınama Veritabanını Üretimle Eşleştirme
Bellek içi SQLite hızlıdır; ancak lehçe farklılıkları (büyük-küçük harf duyarlılığı, JSON işlevleri, yabancı anahtar zorlaması, türler), yalnızca gerçek motorunuzda ortaya çıkan hataları gizleyebilir. Motor özelinde SQL kullanan kodlar için tümleştirme sınamalarını uygun bir yedek yerine üretimdekiyle aynı motora karşı çalıştırın — CI içinde genellikle geçici bir Docker kapsayıcısı kullanılır.
<?php
// Read connection from environment so CI points at a real Postgres/MySQL container
$dsn = getenv('TEST_DATABASE_URL') ?: 'sqlite::memory:';
$pdo = new \PDO($dsn);
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
// In CI, TEST_DATABASE_URL targets the same engine as production.
Kısa Kontrol
İşlevsel bir sınama, üçüncü taraf ödeme sağlayıcısını nasıl ele almalıdır?
Özet
Bileşenleri birlikte sınamayı öğrendiniz:
- Tümleştirme sınamaları, sahte nesnelerin gizlediği şeyleri yakalamak için gerçek veritabanları/hizmetleri kullanır; bunları işlem geri almayla yalıtın.
- İşlevsel sınamalar, benzetilmiş isteklerle gerçek çekirdeği çalıştırır ve yanıtlar ile yan etkiler üzerinde doğrulama yapar.
- Üreticiler en az miktarda veriyi oluşturur; yalnızca en dıştaki harici sınırları sahteleyin.
- Sınama kümelerini hıza göre ayırın ve yavaş sınamaları belirlenimli tutun.
Sıradaki konu: mutasyon sınamasıyla sınama kalitesini ölçmek.
Sıkça Sorulan Sorular
“Entegrasyon ve İşlevsel Test” dersi ücretsiz mi?
Evet — “Entegrasyon ve İşlevsel Test” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve PHP Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. PHP Academy kursu toplamda 4 dersten oluşur.
“Entegrasyon ve İşlevsel Test” dersinde ne öğreneceğim?
Bileşenlerin gerçekte birlikte nasıl çalıştığını test edin. PHP Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
PHP Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te PHP Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.
“Entegrasyon ve İşlevsel Test” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu PHP Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her PHP Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Test Odaklı Geliştirme İş Akışı
- Mockery ile Taklit ve Sahte Nesne Kullanımı
- Entegrasyon ve İşlevsel Test
- Infection ile Mutasyon Testi