Yardımcı Sınıflar
HttpAssert
Tester\HttpAssert sınıfı, HTTP sunucularını test etmek için araçlar sunar. Akıcı bir arayüzle HTTP
istekleri yapmanızı ve durum kodlarını, header'ları ve yanıt gövdesinin içeriğini kolayca doğrulamanızı sağlar.
# Temel HTTP isteği ve yanıt doğrulaması
$response = Tester\HttpAssert::fetch('https://example.com/api/users');
$response
->expectCode(200)
->expectHeader('Content-Type', contains: 'json')
->expectBody(contains: 'users');
fetch() metodu varsayılan olarak bir GET isteği oluşturur, ama tüm parametreler özelleştirilebilir:
HttpAssert::fetch(
'https://api.example.com/users',
method: 'POST',
headers: [
'Authorization' => 'Bearer token123', # ilişkisel dizi
'Accept: application/json', # ya da dize biçimi
],
cookies: ['session' => 'abc123'],
follow: false, # yönlendirmeleri izleme
body: '{"name": "John"}'
)
->expectCode(201);
Durum kodları expectCode() ve denyCode() metotlarıyla doğrulanabilir. Belirli bir sayı ya da bir
doğrulama fonksiyonu verebilirsiniz:
$response
->expectCode(200) # tam kod
->expectCode(fn($code) => $code < 400) # özel doğrulama
->denyCode(404) # 404 olmamalı
->denyCode(fn($code) => $code >= 500); # sunucu hatası olmamalı
Header doğrulaması için expectHeader() ve denyHeader() metotlarını kullanın. Bir header'ın var
olup olmadığını denetleyebilir, tam değerini doğrulayabilir ya da içeriğinin bir parçasını eşleştirebilirsiniz:
$response
->expectHeader('Content-Type') # header var olmalı
->expectHeader('Content-Type', 'application/json') # tam değer
->expectHeader('Content-Type', contains: 'json') # metin içerir
->expectHeader('Server', matches: 'nginx %a%') # desene uyar
->denyHeader('X-Powered-By') # header olmamalı
->denyHeader('X-Debug', contains: 'sensitive') # metin içermemeli
->denyHeader('X-Debug', matches: '~debug~i'); # desene uymamalı
Yanıt gövdesi doğrulaması expectBody() ve denyBody() metotlarıyla benzer şekilde
çalışır:
$response
->expectBody('OK') # tam değer
->expectBody(contains: '"status": "success"') # JSON parçası içerir
->expectBody(matches: '%A% hello %A%') # desene uyar
->expectBody(fn($body) => json_decode($body) !== null) # özel doğrulama
->denyBody('Error occurred') # tam değere sahip olmamalı
->denyBody(contains: 'error') # metin içermemeli
->denyBody(matches: '~exception|fatal~i'); # desene uymamalı
follow parametresi, HttpAssert'in HTTP yönlendirmelerini nasıl ele alacağını denetler:
# Yönlendirmeyi izlemeden test etme (varsayılan)
HttpAssert::fetch('https://example.com/redirect', follow: false)
->expectCode(301)
->expectHeader('Location', 'https://example.com/new-url');
# Tüm yönlendirmeleri son yanıta dek izleme
HttpAssert::fetch('https://example.com/redirect', follow: true)
->expectCode(200)
->expectBody(contains: 'final content');
DomQuery
Tester\DomQuery, SimpleXMLElement sınıfını genişleten ve HTML ya da XML içinde CSS
seçicileriyle kolay sorgulama sunan bir sınıftır.
# HTML dizesinden DomQuery oluştur
$dom = Tester\DomQuery::fromHtml('
<article class="post">
<h1>Title</h1>
<div class="content">Text</div>
</article>
');
# CSS seçicileriyle eleman varlığını test et
Assert::true($dom->has('article.post'));
Assert::true($dom->has('h1'));
# elemanları DomQuery nesnelerinden oluşan bir dizi olarak bul
$headings = $dom->find('h1');
Assert::same('Title', (string) $headings[0]);
# elemanın seçiciye uyup uymadığını test et (2.5.3 sürümünden beri)
$content = $dom->find('.content')[0];
Assert::true($content->matches('div'));
Assert::false($content->matches('p'));
# seçiciye uyan en yakın atayı bul (2.5.5 sürümünden beri)
$article = $content->closest('.post');
Assert::true($article->matches('article'));
XML belgeleri için fromXml() metodunu kullanın:
$dom = Tester\DomQuery::fromXml('<catalog><item>First</item></catalog>');
Assert::true($dom->has('item'));
FileMock
Tester\FileMock, dosyaları bellekte taklit eder ve fopen(), file_get_contents(),
parse_ini_file() gibi fonksiyonları kullanan kodu test etmeyi kolaylaştırır. Örnek kullanım:
# Test edilen sınıf
class Logger
{
public function __construct(
private string $logFile,
) {
}
public function log(string $message): void
{
file_put_contents($this->logFile, $message . "\n", FILE_APPEND);
}
}
# Yeni boş dosya
$file = Tester\FileMock::create('');
$logger = new Logger($file);
$logger->log('Login');
$logger->log('Logout');
# Oluşturulan içeriği test et
Assert::same("Login\nLogout\n", file_get_contents($file));
İsteğe bağlı ikinci parametre $extension, üretilen URL'deki dosya uzantısını ayarlar; test edilen kod buna
göre karar veriyorsa kullanışlıdır:
$file = Tester\FileMock::create('{"key": "value"}', 'json');
Assert::with()
Bu bir assertion değil, nesnelerin private metotlarını ve özelliklerini test etmeye yarayan bir yardımcıdır.
class Entity
{
private $enabled;
// ...
}
$ent = new Entity;
Assert::with($ent, function () {
Assert::true($this->enabled); // private $ent->enabled erişilebilir
});
Helpers::purge()
purge() metodu belirtilen dizini oluşturur, zaten varsa içeriğinin tamamını siler. Geçici bir dizin
oluşturmak için yararlıdır. Örneğin tests/bootstrap.php içinde:
@mkdir(__DIR__ . '/tmp'); # @ - dizin zaten var olabilir
define('TempDir', __DIR__ . '/tmp/' . getmypid());
Tester\Helpers::purge(TempDir);
Environment::lock()
Testler paralel çalışır. Ancak bazen testlerin çalışmasının örtüşmemesi gerekir. Tipik olarak veritabanı testleri,
veritabanı içeriğinin hazırlanmasını ve çalışması sırasında başka hiçbir testin veritabanına karışmamasını
gerektirir. Bu testlerde Tester\Environment::lock($name, $dir) kullanırız:
Tester\Environment::lock('database', __DIR__ . '/tmp');
İlk parametre kilidin adı, ikincisi kilidin saklanacağı dizinin yoludur. Kilidi ilk alan test devam eder, diğer testler onun tamamlanmasını beklemek zorundadır.
Environment::bypassFinals()
final işaretli sınıfları ya da metotları test etmek zordur. Bir testin başında
Tester\Environment::bypassFinals() çağırmak, kod yüklenirken final anahtar sözcüklerinin
atlanmasını sağlar.
require __DIR__ . '/bootstrap.php';
Tester\Environment::bypassFinals();
class MyClass extends NormallyFinalClass # <-- NormallyFinalClass artık final değil
{
// ...
}
Environment::setup()
- hata dökümlerinin okunurluğunu artırır (renklendirme dahil); aksi hâlde PHP'nin varsayılan çağrı yığını yazdırılır
- testte assertion çağrıldığının denetlenmesini sağlar; aksi hâlde assertion'sız testler (örneğin unutulanlar) de geçer
- çalıştırılan kod hakkında bilgi toplamayı otomatik başlatır (
--coveragekullanıldığında) (ayrıntısı aşağıda) - betiğin sonunda OK ya da FAILURE durumunu yazdırır
Environment::setupFunctions()
Testlerinizi yapılandırabileceğiniz genel test(), testException(), testNoError(),
setUp() ve tearDown() fonksiyonlarını oluşturur.
test('test açıklaması', function () {
Assert::same(123, foo());
Assert::false(bar());
// ...
});
Environment::VariableRunner
Testin doğrudan mı yoksa Tester üzerinden mi çalıştırıldığını belirlemenizi sağlar.
if (getenv(Tester\Environment::VariableRunner)) {
# Tester tarafından çalıştırıldı
} else {
# başka bir yolla çalıştırıldı
}
Environment::VariableThread
Tester, testleri belirtilen sayıda iş parçacığında paralel çalıştırır. İş parçacığı numarasıyla ilgileniyorsak, onu ortam değişkeninden buluruz:
echo "Running in thread number " . getenv(Tester\Environment::VariableThread);