Assertion'lar
Assertion'lar, gerçek değerin beklenen değerle eşleştiğini onaylamak için kullanılır.
Tester\Assert sınıfının metotlarıdır.
En uygun assertion'ı seçin. Assert::same($a, $b), Assert::true($a === $b) ifadesinden daha iyidir;
çünkü başarısızlıkta anlamlı bir hata mesajı gösterir. İkinci durumda yalnızca false should be true
alırız ve bu, $a ile $b değişkenlerinin içeriği hakkında bize hiçbir şey söylemez.
Assertion'ların çoğu, beklenti sağlanmazsa hata mesajında görüntülenen isteğe bağlı bir $description
parametresi de alabilir.
Örnekler, şu takma adın oluşturulduğunu varsayar:
use Tester\Assert;
Assert::same ($expected, $actual, ?string $description=null)
$expected, $actual ile özdeş olmalıdır. PHP'nin === operatörüyle aynıdır.
Assert::notSame ($expected, $actual, ?string $description=null)
Assert::same() metodunun tersi; yani PHP'nin !== operatörüyle aynıdır.
Assert::equal ($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false)
$expected, $actual değerine eşit olmalıdır. Assert::same() metodunun aksine nesne
özdeşliği, dizilerdeki anahtar ⇒ değer çiftlerinin sırası ve çok az farklı ondalık sayılar yok sayılır; bu,
$matchIdentity ve $matchOrder ayarlanarak değiştirilebilir.
Şu durumlar equal() açısından eşittir, ama same() açısından değildir:
Assert::equal(0.3, 0.1 + 0.2);
Assert::equal($obj, clone $obj);
Assert::equal(
['first' => 11, 'second' => 22],
['second' => 22, 'first' => 11],
);
Ama dikkat: [1, 2] ve [2, 1] dizileri aynı değildir; çünkü yalnızca değerlerin sırası
farklıdır, anahtar ⇒ değer çiftlerinin değil. [1, 2] dizisi [0 => 1, 1 => 2] olarak da
yazılabilir, dolayısıyla [1 => 2, 0 => 1] aynı sayılır.
$expected içinde Beklentiler denen yapıları da kullanabilirsiniz.
Assert::notEqual ($expected, $actual, ?string $description=null)
Assert::equal() metodunun tersi.
Assert::contains ($needle, string|array $actual, ?string $description=null)
$actual bir dizeyse, $needle alt dizesini içermelidir. Bir diziyse, $needle öğesini
içermelidir (katı karşılaştırma yapılır).
Assert::notContains ($needle, string|array $actual, ?string $description=null)
Assert::contains() metodunun tersi.
Assert::hasKey (string|int $needle, array $actual, ?string $description=null)
$actual bir dizi olmalı ve $needle anahtarını içermelidir.
Assert::hasNotKey (string|int $needle, array $actual, ?string $description=null)
$actual bir dizi olmalı ve $needle anahtarını içermemelidir.
Assert::true ($value, ?string $description=null)
$value, true olmalıdır; yani $value === true.
Assert::truthy ($value, ?string $description=null)
$value doğruluk değeri taşımalıdır; yani if ($value) ... koşulunu sağlamalıdır.
Assert::false ($value, ?string $description=null)
$value, false olmalıdır; yani $value === false.
Assert::falsey ($value, ?string $description=null)
$value yanlışlık değeri taşımalıdır; yani if (!$value) ... koşulunu sağlamalıdır.
Assert::null ($value, ?string $description=null)
$value, null olmalıdır; yani $value === null.
Assert::notNull ($value, ?string $description=null)
$value, null olmamalıdır; yani $value !== null.
Assert::nan ($value, ?string $description=null)
$value, Not a Number olmalıdır. NAN değerlerini test etmek için yalnızca Assert::nan()
kullanın. NAN değeri çok özeldir ve Assert::same() ya da Assert::equal() gibi assertion'lar
beklenmedik davranabilir.
Assert::count ($count, Countable|array $value, ?string $description=null)
$value içindeki öğe sayısı $count olmalıdır. count($value) === $count ile
aynıdır.
Assert::type (string|object $type, $value, ?string $description=null)
$value verilen türde olmalıdır. $type olarak bir dize kullanabiliriz:
arraylist– sıfırdan başlayan artan sayısal anahtarlarla indekslenmiş diziboolcallablefloatintnullobjectresourcescalarstring- sınıf adı ya da doğrudan bir nesne; o zaman
$value instanceof $typeolmalıdır
Assert::exception (callable $callable, string $class, ?string $message=null, $code=null)
$callable çağrıldığında $class sınıfından bir istisna fırlatılmalıdır.
$message belirtirsek, istisnanın mesajı da desene uymalıdır. $code
belirtirsek, kodlar da tam olarak eşleşmelidir.
Örneğin aşağıdaki test, istisna mesajı uymadığı için başarısız olacak:
Assert::exception(
fn() => throw new App\InvalidValueException('Zero value'),
App\InvalidValueException::class,
'Value is too low',
);
Assert::exception(), fırlatılan istisnayı döndürür; böylece iç içe bir istisnayı da test
edebilirsiniz.
$e = Assert::exception(
fn() => throw new MyException('Something is wrong', 0, new RuntimeException),
MyException::class,
'Something is wrong',
);
Assert::type(RuntimeException::class, $e->getPrevious());
Assert::error (string $callable, int|string|array $type, ?string $message=null)
$callable fonksiyonunun beklenen hataları (yani uyarıları, notice'ları vb.) ürettiğini denetler.
$type olarak E_... sabitlerinden birini, örneğin E_WARNING belirtin.
$message belirtirsek, hata mesajı da desene uymalıdır. Örneğin:
Assert::error(
fn() => $i++,
E_NOTICE,
'Undefined variable: i',
);
Callback daha fazla hata üretiyorsa, hepsini tam olarak aynı sırayla beklemeliyiz. Bu durumda $type içinde bir
dizi verin:
Assert::error(function () {
$a++;
$b++;
}, [
[E_NOTICE, 'Undefined variable: a'],
[E_NOTICE, 'Undefined variable: b'],
]);
$type olarak sınıf adı belirtirseniz, Assert::exception() ile aynı şekilde
davranır.
Assert::noError (callable $callable)
$callable fonksiyonunun hiçbir uyarı, hata ya da istisna üretmediğini denetler. Başka assertion'ın
bulunmadığı kod parçalarını test etmek için yararlıdır.
Assert::match (string $pattern, $actual, ?string $description=null)
$actual, $pattern desenine uymalıdır. Desenlerin iki varyantını kullanabiliriz: düzenli ifadeler
ya da joker karakterler.
$pattern olarak bir düzenli ifade verirsek, onu sınırlamak için ~ ya da #
kullanmalıyız. Başka sınırlayıcılar desteklenmez. Örneğin $var değişkeninin yalnızca onaltılık rakam
içermesi gereken bir test:
Assert::match('#^[0-9a-f]+$#i', $var);
İkinci varyant sıradan dizeleri karşılaştırmaya benzer, ama $pattern içinde çeşitli joker karakterler
kullanabiliriz:
%a%satır sonu karakterleri dışında bir ya da daha fazla herhangi bir şey%a?%satır sonu karakterleri dışında sıfır ya da daha fazla herhangi bir şey%A%satır sonu karakterleri dahil bir ya da daha fazla herhangi bir şey%A?%satır sonu karakterleri dahil sıfır ya da daha fazla herhangi bir şey%s%satır sonu karakterleri dışında bir ya da daha fazla boşluk karakteri%s?%satır sonu karakterleri dışında sıfır ya da daha fazla boşluk karakteri%S%boşluk karakterleri dışında bir ya da daha fazla karakter%S?%boşluk karakterleri dışında sıfır ya da daha fazla karakter%c%herhangi bir türden tek bir karakter (satır sonu dışında)%d%bir ya da daha fazla rakam%d?%sıfır ya da daha fazla rakam%i%işaretli tam sayı değeri%f%kayan noktalı sayı%h%bir ya da daha fazla onaltılık rakam%w%bir ya da daha fazla alfanümerik karakter%ds%dizin ayırıcı (/ya da\)%%bir % karakteri
Örnekler:
# Yine onaltılık sayı testi
Assert::match('%h%', $var);
# Dosya yolunun ve satır numarasının genelleştirilmesi
Assert::match('Error in file %a% on line %i%', $errorMessage);
Assert::notMatch (string $pattern, $actual, ?string $description=null)
Assert::match() metodunun tersi.
Assert::matchFile (string $file, $actual, ?string $description=null)
Bu assertion Assert::match() ile aynıdır, ama desen $file dosyasından
yüklenir. Bu, çok uzun dizeleri test etmek için yararlıdır. Test dosyası derli toplu kalır.
Assert::fail (string $message, $actual=null, $expected=null)
Bu assertion her zaman başarısız olur. Bazen tam da işe yarar. İsteğe bağlı olarak beklenen ve gerçek değeri belirtebiliriz.
Beklentiler
Sabit olmayan öğeler içeren daha karmaşık yapıları karşılaştırmak istediğimizde, yukarıda sözü edilen
assertion'lar yetmeyebilir. Örneğin yeni bir kullanıcı oluşturup özniteliklerini dizi olarak döndüren bir metodu test
ediyoruz. Parola hash'inin değerini bilmiyoruz, ama onun onaltılık bir dize olması gerektiğini biliyoruz. Bir sonraki öğe
hakkında ise yalnızca bir DateTime nesnesi olması gerektiğini biliyoruz.
Bu durumlarda, Assert::equal() ve Assert::notEqual() metotlarının $expected
parametresinin içinde Tester\Expect kullanabiliriz; onunla yapı kolayca anlatılabilir.
use Tester\Expect;
Assert::equal([
'id' => Expect::type('int'), # bir tam sayı bekliyoruz
'username' => 'milo',
'password' => Expect::match('%h%'), # desene uyan bir dize bekliyoruz
'created_at' => Expect::type(DateTime::class), # sınıfın bir örneğini bekliyoruz
], User::create(123, 'milo', 'RandomPaSsWoRd'));
Expect ile, Assert ile yaptığımız assertion'ların neredeyse aynısını yapabiliriz. Böylece
Expect::same(), Expect::match(), Expect::count() gibi metotlar elimizin altındadır.
Ayrıca onları zincirleyebiliriz:
Expect::type(MyIterator::class)->andCount(5); # MyIterator bekliyoruz ve öğe sayısı 5
Alternatif olarak kendi assertion işleyicilerimizi yazabiliriz.
Expect::that(function ($value) {
# beklenti sağlanmazsa false döndür
});
Başarısız Assertion'ları İnceleme
Bir assertion başarısız olduğunda Tester, hatanın ne olduğunu yazdırır. Karmaşık yapıları karşılaştırıyorsak,
Tester karşılaştırılan değerlerin dökümlerini oluşturur ve output dizinine kaydeder. Örneğin varsayımsal
Arrays.recursive.phpt testi başarısız olursa dökümler şöyle saklanır:
app/
└── tests/
├── output/
│ ├── Arrays.recursive.actual # gerçek değer
│ └── Arrays.recursive.expected # beklenen değer
│
└── Arrays.recursive.phpt # başarısız test
Dizin adını Tester\Dumper::$dumpDir ile değiştirebiliriz.