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ş dizibool
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.