Behauptungen
Aassertions werden verwendet, um zu behaupten, dass ein tatsächlicher Wert mit einem erwarteten Wert
übereinstimmt. Sie sind Methoden des Tester\Assert
.
Wählen Sie die genauesten Behauptungen. Assert::same($a, $b)
ist besser als Assert::true($a === $b)
,
weil es bei Fehlern eine sinnvolle Fehlermeldung anzeigt. Im zweiten Fall erhalten wir nur false should be true
und
es sagt nichts über den Inhalt der Variablen $a und $b aus.
Die meisten Assertions können auch eine optionale $description
haben, die in der Fehlermeldung erscheint, wenn
die Erwartung fehlschlägt.
Beispiele nehmen an, dass der folgende Klassenalias definiert ist:
use Tester\Assert;
Assert::same ($expected, $actual, ?string $description=null)
$expected
muss mit $actual
identisch sein. Er ist identisch mit dem PHP-Operator
===
.
Assert::notSame ($expected, $actual, ?string $description=null)
Das Gegenteil von Assert::same()
, also dasselbe wie der PHP-Operator !==
.
Assert::equal ($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false)
$expected
muss mit $actual
identisch sein. Im Gegensatz zu Assert::same()
werden
Objektidentität, Reihenfolge von Schlüsselpaaren ⇒ Wert in Arrays und geringfügig unterschiedliche Dezimalzahlen ignoriert,
was durch Setzen von $matchIdentity
und $matchOrder
geändert werden kann.
Die folgenden Fälle sind aus der Sicht von equal()
identisch, aber nicht für same()
:
Assert::equal(0.3, 0.1 + 0.2);
Assert::equal($obj, clone $obj);
Assert::equal(
['first' => 11, 'second' => 22],
['second' => 22, 'first' => 11],
);
Beachten Sie jedoch, dass das Array [1, 2]
und [2, 1]
sind nicht gleich, da sich nur die Reihenfolge
der Werte unterscheidet, nicht aber die Schlüssel ⇒ Wertpaare. Das Array [1, 2]
kann auch geschrieben werden als
[0 => 1, 1 => 2]
geschrieben werden und daher [1 => 2, 0 => 1]
als gleich betrachtet
werden.
Sie können auch die sogenannten Erwartungen in $expected
verwenden.
Assert::notEqual ($expected, $actual, ?string $description=null)
Im Gegensatz zu Assert::equal()
.
Assert::contains ($needle, string|array $actual, ?string $description=null)
Wenn $actual
eine Zeichenkette ist, muss sie die Teilzeichenkette $needle
enthalten. Wenn es sich um
ein Array handelt, muss es das Element $needle
enthalten (es wird streng verglichen).
Assert::notContains ($needle, string|array $actual, ?string $description=null)
Im Gegensatz zu Assert::contains()
.
Assert::hasKey (string|int $needle, array $actual, ?string $description=null)
$actual
muss ein Array sein und den Schlüssel $needle
enthalten.
Assert::notHasKey (string|int $needle, array $actual, ?string $description=null)
$actual
muss ein Array sein und darf den Schlüssel $needle
nicht enthalten.
Assert::true ($value, ?string $description=null)
$value
muss true
sein, also $value === true
.
Assert::truthy ($value, ?string $description=null)
$value
muss wahrheitsgemäß sein, also erfüllt es die Bedingung if ($value) ...
.
Assert::false ($value, ?string $description=null)
$value
muss false
sein, also $value === false
.
Assert::falsey ($value, ?string $description=null)
$value
muss falsch sein, also erfüllt es die Bedingung if (!$value) ...
.
Assert::null ($value, ?string $description=null)
$value
muss null
sein, also $value === null
.
Assert::notNull ($value, ?string $description=null)
$value
darf nicht null
sein, also $value !== null
.
Assert::nan ($value, ?string $description=null)
$value
muss Not a Number sein. Verwenden Sie für NAN-Tests nur die Assert::nan()
. Der NAN-Wert ist
sehr spezifisch und die Assertions Assert::same()
oder Assert::equal()
können sich unvorhersehbar
verhalten.
Assert::count ($count, Countable|array $value, ?string $description=null)
Die Anzahl der Elemente in $value
muss $count
sein. Also dasselbe wie
count($value) === $count
.
Assert::type (string|object $type, $value, ?string $description=null)
$value
muss von einem bestimmten Typ sein. Als $type
können wir String verwenden:
array
list
– Array, das in aufsteigender Reihenfolge der numerischen Schlüssel von Null an indiziert istbool
callable
float
int
null
object
resource
scalar
string
- Klassenname oder Objekt direkt, dann müssen
$value instanceof $type
Assert::exception (callable $callable, string $class, ?string $message=null, $code=null)
Beim Aufruf von $callable
muss eine Ausnahme der Instanz $class
ausgelöst werden. Wenn wir
$message
übergeben, muss die Nachricht der Ausnahme übereinstimmen. Und wenn wir
$code
übergeben, muss der Code der Ausnahme derselbe sein.
Dieser Test schlägt zum Beispiel fehl, weil die Meldung der Ausnahme nicht übereinstimmt:
Assert::exception(
fn() => throw new App\InvalidValueException('Zero value'),
App\InvalidValueException::class,
'Value is to low',
);
Die Assert::exception()
gibt eine ausgelöste Ausnahme zurück, so dass Sie eine verschachtelte Ausnahme testen
können.
$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)
Überprüft, ob der $callable
-Aufruf die erwarteten Fehler erzeugt (d.h. Warnungen, Hinweise usw.). Als
$type
geben wir eine der Konstanten E_...
an, zum Beispiel E_WARNING
. Und wenn wir
$message
übergeben, muss die Fehlermeldung auch dem Muster entsprechen. Zum Beispiel:
Assert::error(
fn() => $i++,
E_NOTICE,
'Undefined variable: i',
);
Wenn der Rückruf mehrere Fehler erzeugt, müssen wir alle in der genauen Reihenfolge erwarten. In diesem Fall übergeben wir
das Array in $type
:
Assert::error(function () {
$a++;
$b++;
}, [
[E_NOTICE, 'Undefined variable: a'],
[E_NOTICE, 'Undefined variable: b'],
]);
Wenn $type
ein Klassenname ist, verhält sich diese Assertion genauso wie
Assert::exception()
.
Assert::noError (callable $callable)
Überprüft, dass die Funktion $callable
keine PHP-Warnung/Hinweis/Fehler oder Ausnahme auslöst. Sie ist
nützlich, um ein Stück Code zu testen, für das es keine andere Assertion gibt.
Assert::match (string $pattern, $actual, ?string $description=null)
$actual
muss mit $pattern
übereinstimmen. Wir können zwei Varianten von Mustern verwenden:
reguläre Ausdrücke oder Wildcards.
Wenn wir einen regulären Ausdruck als $pattern
übergeben, müssen wir ~
or #
verwenden, um ihn abzugrenzen. Andere Begrenzungszeichen werden nicht unterstützt. Zum Beispiel test, bei dem $var
nur hexadezimale Ziffern enthalten darf:
Assert::match('#^[0-9a-f]$#i', $var);
Die andere Variante ähnelt dem Vergleich von Zeichenketten, aber wir können einige Platzhalterzeichen in
$pattern
verwenden:
%a%
ein oder mehrere beliebige Zeichen außer den Zeilenendezeichen%a?%
null oder mehr von irgendetwas, außer den Zeilenendezeichen%A%
ein oder mehrere beliebige Zeichen einschließlich der Zeilenendezeichen%A?%
null oder mehr von irgendetwas, einschließlich der Zeilenendezeichen%s%
ein oder mehrere Leerzeichen mit Ausnahme der Zeilenendezeichen%s?%
keine oder mehrere Leerzeichen, ausgenommen Zeilenende-Zeichen%S%
ein oder mehrere Zeichen mit Ausnahme des Leerzeichens%S?%
keine oder mehrere Zeichen außer dem Leerzeichen%c%
ein einzelnes Zeichen beliebiger Art (außer dem Zeilenende)%d%
eine oder mehrere Ziffern%d?%
keine oder mehrere Ziffern%i%
vorzeichenbehafteter Integer-Wert%f%
Gleitkommazahl%h%
eine oder mehrere HEX-Ziffern%w%
ein oder mehrere alphanumerische Zeichen%%
ein %-Zeichen
Beispiele:
# Again, hexadecimal number test
Assert::match('%h%', $var);
# Generalized path to file and line number
Assert::match('Error in file %a% on line %i%', $errorMessage);
Assert::matchFile (string $file, $actual, ?string $description=null)
Die Assertion ist identisch mit Assert::match(), aber das Muster wird von $file
geladen. Sie ist nützlich für das Testen sehr langer Strings. Die Testdatei ist lesbar.
Assert::fail (string $message, $actual=null, $expected=null)
Diese Behauptung schlägt immer fehl. Sie ist einfach praktisch. Wir können optional erwartete und tatsächliche Werte übergeben.
Erwartungen
Wenn wir komplexere Strukturen mit nicht konstanten Elementen vergleichen wollen, sind die obigen Aussagen möglicherweise
nicht ausreichend. Wir testen zum Beispiel eine Methode, die einen neuen Benutzer erstellt und seine Attribute als Array
zurückgibt. Wir kennen den Hashwert des Kennworts nicht, aber wir wissen, dass es eine hexadezimale Zeichenkette sein muss. Und
das einzige, was wir über das nächste Element wissen, ist, dass es ein Objekt DateTime
sein muss.
In diesen Fällen können wir Tester\Expect
innerhalb des $expected
-Parameters der
Assert::equal()
– und Assert::notEqual()
-Methoden verwenden, mit denen sich die Struktur leicht
beschreiben lässt.
use Tester\Expect;
Assert::equal([
'id' => Expect::type('int'), # we expect an integer
'username' => 'milo',
'password' => Expect::match('%h%'), # we expect a string matching pattern
'created_at' => Expect::type(DateTime::class), # we expect an instance of the class
], User::create(123, 'milo', 'RandomPaSsWoRd'));
Mit Expect
können wir fast die gleichen Behauptungen aufstellen wie mit Assert
. Wir haben also
Methoden wie Expect::same()
, Expect::match()
, Expect::count()
, usw. Darüber hinaus können
wir sie wie folgt verketten:
Expect::type(MyIterator::class)->andCount(5); # we expect MyIterator and items count is 5
Oder wir können eigene Assertion Handler schreiben.
Expect::that(function ($value) {
# return false if expectation fails
});
Untersuchung fehlgeschlagener Assertions
Der Tester zeigt an, wo der Fehler liegt, wenn eine Assertion fehlschlägt. Wenn wir komplexe Strukturen vergleichen, erstellt
der Tester Dumps der verglichenen Werte und speichert sie im Verzeichnis output
. Wenn zum Beispiel der imaginäre
Test Arrays.recursive.phpt
fehlschlägt, werden die Dumps wie folgt gespeichert:
app/
└── tests/
├── output/
│ ├── Arrays.recursive.actual # actual value
│ └── Arrays.recursive.expected # expected value
│
└── Arrays.recursive.phpt # failing test
Wir können den Namen des Verzeichnisses mit Tester\Dumper::$dumpDir
ändern.