Doğrulama İfadeleri (Assertion)

Doğrulama ifadeleri, gerçek değerin beklenen değere karşılık geldiğini onaylamak için kullanılır. Bunlar Tester\Assert sınıfının metotlarıdır.

En uygun doğrulama ifadelerini seçin. Assert::same($a, $b), Assert::true($a === $b)'den daha iyidir, çünkü başarısız olduğunda anlamlı bir hata mesajı gösterir. İkinci durumda, yalnızca $a ve $b değişkenlerinin içeriği hakkında hiçbir şey söylemeyen false should be true mesajı gösterilir.

Çoğu doğrulama ifadesi ayrıca, beklenti başarısız olursa hata mesajında gösterilecek olan isteğe bağlı bir $description parametresine sahip olabilir.

Örnekler, bir takma adın oluşturulduğunu varsayar:

use Tester\Assert;

Assert::same ($expected, $actual, ?string $description=null)

$expected, $actual ile aynı olmalıdır. PHP === operatörü ile aynıdır.

Assert::notSame ($expected, $actual, ?string $description=null)

Assert::same()'in tersi, yani PHP !== operatörü ile aynıdır.

Assert::equal ($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false)

$expected, $actual ile aynı olmalıdır. Assert::same()'den farklı olarak, nesnelerin kimliği, dizilerdeki anahtar ⇒ değer çiftlerinin sırası ve marjinal olarak farklı ondalık sayılar göz ardı edilir, bu $matchIdentity ve $matchOrder ayarlanarak değiştirilebilir.

Aşağıdaki durumlar equal() açısından aynıdır, ancak 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],
);

Ancak dikkat, [1, 2] ve [2, 1] dizileri aynı değildir, çünkü yalnızca değerlerin sırası farklıdır, anahtar ⇒ değer çiftlerinin sırası değil. [1, 2] dizisi ayrıca [0 => 1, 1 => 2] olarak da yazılabilir ve bu nedenle [1 => 2, 0 => 1] aynı kabul edilecektir.

Ayrıca $expected içinde sözde beklentiler kullanılabilir.

Assert::notEqual ($expected, $actual, ?string $description=null)

Assert::equal()'in tersi.

Assert::contains ($needle, string|array $actual, ?string $description=null)

Eğer $actual bir karakter dizisi ise, $needle alt karakter dizisini içermelidir. Eğer bir dizi ise, $needle öğesini içermelidir (kesin olarak karşılaştırılır).

Assert::notContains ($needle, string|array $actual, ?string $description=null)

Assert::contains()'in tersi.

Assert::hasKey (string|int $needle, array $actual, ?string $description=null)

$actual bir dizi olmalı ve $needle anahtarını içermelidir.

Assert::notHasKey (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ğru olmalıdır, yani if ($value) ... koşulunu karşı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ış olmalıdır, yani if (!$value) ... koşulunu karşı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() veya Assert::equal() doğrulama ifadeleri beklenmedik şekilde çalışabilir.

Assert::count ($count, Countable|array $value, ?string $description=null)

$value içindeki öğelerin sayısı $count olmalıdır. Yani count($value) === $count ile aynıdır.

Assert::type (string|object $type, $value, ?string $description=null)

$value belirtilen türde olmalıdır. $type olarak bir karakter dizisi kullanabiliriz:

  • array
  • list – sıfırdan başlayarak artan sayısal anahtarlara göre indekslenmiş dizi
  • bool
  • callable
  • float
  • int
  • null
  • object
  • resource
  • scalar
  • string
  • bir sınıf adı veya doğrudan bir nesne, o zaman $value instanceof $type olmalıdır

Assert::exception (callable $callable, string $class, ?string $message=null, $code=null)

$callable çağrıldığında, $class sınıfının bir istisnası atılmalıdır. Eğer $message belirtirsek, istisna mesajı da desene uymalıdır ve eğer $code belirtirsek, kodlar da kesin olarak eşleşmelidir.

Aşağıdaki test, istisna mesajı eşleşmediği için başarısız olur:

Assert::exception(
	fn() => throw new App\InvalidValueException('Sıfır değeri'),
	App\InvalidValueException::class,
	'Değer çok düşük',
);

Assert::exception() atılan istisnayı döndürür, böylece iç içe geçmiş istisnaları da test edebilirsiniz.

$e = Assert::exception(
	fn() => throw new MyException('Bir şeyler yanlış', 0, new RuntimeException),
	MyException::class,
	'Bir şeyler yanlış',
);

Assert::type(RuntimeException::class, $e->getPrevious());

Assert::error (string $callable, int|string|array $type, ?string $message=null)

$callable fonksiyonunun beklenen hataları (yani uyarılar, bildirimler vb.) oluşturup oluşturmadığını kontrol eder. $type olarak E_... sabitlerinden birini, örneğin E_WARNING belirtiriz. Ve eğer $message belirtirsek, hata mesajı da desene uymalıdır. Örneğin:

Assert::error(
	fn() => $i++,
	E_NOTICE,
	'Tanımsız değişken: i',
);

Eğer geri arama birden fazla hata oluşturursa, hepsini tam sırada beklemeliyiz. Bu durumda $type içinde bir dizi aktarırız:

Assert::error(function () {
	$a++;
	$b++;
}, [
	[E_NOTICE, 'Tanımsız değişken: a'],
	[E_NOTICE, 'Tanımsız değişken: b'],
]);

Eğer $type olarak bir sınıf adı belirtirseniz, Assert::exception() ile aynı şekilde davranır.

Assert::noError (callable $callable)

$callable fonksiyonunun herhangi bir uyarı, hata veya istisna oluşturmadığını kontrol eder. Başka bir doğrulama ifadesi olmayan kod parçalarını test etmek için kullanışlıdır.

Assert::match (string $pattern, $actual, ?string $description=null)

$actual, $pattern desenine uymalıdır. İki desen türü kullanabiliriz: düzenli ifadeler veya joker karakterler.

Eğer $pattern olarak bir düzenli ifade aktarırsak, onu sınırlamak için ~ veya # kullanmalıyız, diğer sınırlayıcılar desteklenmez. Örneğin, $var'ın yalnızca onaltılık rakamlar içermesi gereken test:

Assert::match('#^[0-9a-f]$#i', $var);

İkinci varyant, sıradan karakter dizisi karşılaştırmasına benzer, ancak $pattern içinde farklı joker karakterler kullanabiliriz:

  • %a% satır sonu karakterleri hariç bir veya daha fazla karakter
  • %a?% satır sonu karakterleri hariç sıfır veya daha fazla karakter
  • %A% satır sonu karakterleri dahil bir veya daha fazla karakter
  • %A?% satır sonu karakterleri dahil sıfır veya daha fazla karakter
  • %s% satır sonu karakterleri hariç bir veya daha fazla boşluk karakteri
  • %s?% satır sonu karakterleri hariç sıfır veya daha fazla boşluk karakteri
  • %S% boşluk karakterleri hariç bir veya daha fazla karakter
  • %S?% boşluk karakterleri hariç sıfır veya daha fazla karakter
  • %c% satır sonu karakteri hariç herhangi bir tek karakter
  • %d% bir veya daha fazla rakam
  • %d?% sıfır veya daha fazla rakam
  • %i% işaretli tamsayı değeri
  • %f% ondalık noktalı sayı
  • %h% bir veya daha fazla onaltılık rakam
  • %w% bir veya daha fazla alfasayısal karakter
  • %% % karakteri

Örnekler:

# Yine onaltılık sayı testi
Assert::match('%h%', $var);

# Dosya yolunun ve satır numarasının genelleştirilmesi
Assert::match('Dosyadaki hata %a% satır %i%', $errorMessage);

Assert::matchFile (string $file, $actual, ?string $description=null)

Doğrulama ifadesi Assert::match() ile aynıdır, ancak desen $file dosyasından yüklenir. Bu, çok uzun karakter dizilerini test etmek için kullanışlıdır. Test dosyası düzenli kalır.

Assert::fail (string $message, $actual=null, $expected=null)

Bu doğrulama ifadesi her zaman başarısız olur. Bazen bu sadece kullanışlıdır. İsteğe bağlı olarak beklenen ve gerçek değerleri de belirtebiliriz.

Beklentiler

Sabit olmayan öğelerle daha karmaşık yapıları karşılaştırmak istediğimizde, yukarıdaki doğrulama ifadeleri yeterli olmayabilir. Örneğin, yeni bir kullanıcı oluşturan ve niteliklerini bir dizi olarak döndüren bir metodu test ediyoruz. Şifre hash değerini bilmiyoruz, ancak onaltılık bir karakter dizisi olması gerektiğini biliyoruz. Ve başka bir öğe hakkında sadece bir DateTime nesnesi olması gerektiğini biliyoruz.

Bu durumlarda, Assert::equal() ve Assert::notEqual() metotlarının $expected parametresi içinde Tester\Expect kullanabiliriz, bu sayede yapıyı kolayca tanımlayabiliriz.

use Tester\Expect;

Assert::equal([
	'id' => Expect::type('int'),                   # tamsayı bekliyoruz
	'username' => 'milo',
	'password' => Expect::match('%h%'),            # desene uyan karakter dizisi bekliyoruz
	'created_at' => Expect::type(DateTime::class), # sınıfın bir örneğini bekliyoruz
], User::create(123, 'milo', 'RandomPaSsWoRd'));

Expect ile Assert ile neredeyse aynı doğrulama ifadelerini yapabiliriz. Yani, Expect::same(), Expect::match(), Expect::count() vb. metotlar bizim için kullanılabilir. Ayrıca, onları zincirleyebiliriz:

Expect::type(MyIterator::class)->andCount(5);  # MyIterator ve 5 öğe sayısı bekliyoruz

Veya kendi doğrulama ifadesi işleyicilerimizi yazabiliriz.

Expect::that(function ($value) {
	# beklenti başarısız olursa false döndürün
});

Hatalı Doğrulama İfadelerini İnceleme

Bir doğrulama ifadesi başarısız olduğunda, Tester hatanın ne olduğunu yazdırır. Daha karmaşık yapıları karşılaştırıyorsak, Tester karşılaştırılan değerlerin dökümlerini oluşturur ve bunları output dizinine kaydeder. Örneğin, hayali Arrays.recursive.phpt testinin başarısız olması durumunda, dökümler aşağıdaki gibi kaydedilecektir:

app/
└── tests/
	├── output/
	│   ├── Arrays.recursive.actual    # gerçek değer
	│   └── Arrays.recursive.expected  # beklenen değer
	│
	└── Arrays.recursive.phpt          # başarısız olan test

Dizin adını Tester\Dumper::$dumpDir aracılığıyla değiştirebiliriz.