Ισχυρισμοί
Οι ισχυρισμοί χρησιμοποιούνται για να βεβαιώνουν ότι μια
πραγματική τιμή ταιριάζει με μια αναμενόμενη τιμή. Είναι μέθοδοι της
Tester\Assert
.
Επιλέξτε τους πιο ακριβείς ισχυρισμούς. Είναι καλύτερο
Assert::same($a, $b)
από το Assert::true($a === $b)
επειδή εμφανίζει
σημαντικό μήνυμα σφάλματος σε περίπτωση αποτυχίας. Στη δεύτερη
περίπτωση παίρνουμε μόνο το false should be true
και δεν λέει τίποτα για
τα περιεχόμενα των μεταβλητών $a και $b.
Οι περισσότεροι ισχυρισμοί μπορούν επίσης να έχουν ένα προαιρετικό
$description
που εμφανίζεται στο μήνυμα σφάλματος αν η προσδοκία
αποτύχει.
Τα παραδείγματα υποθέτουν ότι έχει οριστεί το ακόλουθο ψευδώνυμο κλάσης:
use Tester\Assert;
Assert::same ($expected, $actual, ?string $description=null)
$expected
πρέπει να είναι το ίδιο με το $actual
. Είναι το ίδιο με
τον τελεστή PHP ===
.
Assert::notSame ($expected, $actual, ?string $description=null)
Αντίθετος του Assert::same()
, άρα είναι ίδιος με τον τελεστή PHP
!==
.
Assert::equal ($expected, $actual, ?string $description=null, bool $matchOrder=false, bool $matchIdentity=false)
$expected
πρέπει να είναι το ίδιο με το $actual
. Σε αντίθεση με
το Assert::same()
, η ταυτότητα αντικειμένων, η σειρά των ζευγών
κλειδιών ⇒ τιμή σε πίνακες και οι οριακά διαφορετικοί δεκαδικοί
αριθμοί αγνοούνται, οι οποίοι μπορούν να αλλάξουν με τη ρύθμιση των
$matchIdentity
και $matchOrder
.
Οι ακόλουθες περιπτώσεις είναι ταυτόσημες από την άποψη του
equal()
, αλλά όχι για το same()
:
Assert::equal(0.3, 0.1 + 0.2);
Assert::equal($obj, clone $obj);
Assert::equal(
['first' => 11, 'second' => 22],
['second' => 22, 'first' => 11],
);
Ωστόσο, προσέξτε, ο πίνακας [1, 2]
και [2, 1]
δεν είναι ίσες,
επειδή διαφέρει μόνο η σειρά των τιμών, όχι τα ζεύγη κλειδί ⇒ τιμή. Ο
πίνακας [1, 2]
μπορεί επίσης να γραφτεί ως [0 => 1, 1 => 2]
και
επομένως [1 => 2, 0 => 1]
θα θεωρηθεί ίσος.
Μπορείτε επίσης να χρησιμοποιήσετε τις λεγόμενες προσδοκίες στο $expected
.
Assert::notEqual ($expected, $actual, ?string $description=null)
Σε αντίθεση με το Assert::equal()
.
Assert::contains ($needle, string|array $actual, ?string $description=null)
Εάν το $actual
είναι μια συμβολοσειρά, πρέπει να περιέχει την
υποσυμβολοσειρά $needle
. Εάν είναι πίνακας, πρέπει να περιέχει το
στοιχείο $needle
(συγκρίνεται αυστηρά).
Assert::notContains ($needle, string|array $actual, ?string $description=null)
Αντίθετο από το Assert::contains()
.
Assert::hasKey (string|int $needle, array $actual, ?string $description=null)
$actual
πρέπει να είναι ένας πίνακας και να περιέχει το κλειδί
$needle
.
Assert::notHasKey (string|int $needle, array $actual, ?string $description=null)
$actual
πρέπει να είναι πίνακας και να μην περιέχει το κλειδί
$needle
.
Assert::true ($value, ?string $description=null)
$value
πρέπει να είναι true
, οπότε $value === true
.
Assert::truthy ($value, ?string $description=null)
$value
πρέπει να είναι αληθές, άρα ικανοποιεί τη συνθήκη
if ($value) ...
.
Assert::false ($value, ?string $description=null)
$value
πρέπει να είναι false
, άρα $value === false
.
Assert::falsey ($value, ?string $description=null)
$value
πρέπει να είναι ψευδής, άρα ικανοποιεί τη συνθήκη
if (!$value) ...
.
Assert::null ($value, ?string $description=null)
$value
πρέπει να είναι null
, άρα $value === null
.
Assert::notNull ($value, ?string $description=null)
$value
δεν πρέπει να είναι null
, οπότε $value !== null
.
Assert::nan ($value, ?string $description=null)
$value
πρέπει να είναι Not a Number. Χρησιμοποιήστε μόνο το
Assert::nan()
για δοκιμές NAN. Η τιμή NAN είναι πολύ συγκεκριμένη και οι
ισχυρισμοί Assert::same()
ή Assert::equal()
μπορεί να συμπεριφέρονται
απρόβλεπτα.
Assert::count ($count, Countable|array $value, ?string $description=null)
Ο αριθμός των στοιχείων στο $value
πρέπει να είναι $count
. Άρα
το ίδιο με το count($value) === $count
.
Assert::type (string|object $type, $value, ?string $description=null)
$value
πρέπει να είναι συγκεκριμένου τύπου. Ως $type
μπορούμε να χρησιμοποιήσουμε το string:
array
list
– πίνακας με ευρετήριο σε αύξουσα σειρά αριθμητικών κλειδιών από το μηδένbool
callable
float
int
null
object
resource
scalar
string
- το όνομα της κλάσης ή του αντικειμένου απευθείας, τότε πρέπει να
περάσει
$value instanceof $type
Assert::exception (callable $callable, string $class, ?string $message=null, $code=null)
Κατά την κλήση του $callable
πρέπει να εκπέμπεται μια εξαίρεση της
περίπτωσης $class
. Αν περάσουμε το $message
, το μήνυμα της
εξαίρεσης πρέπει να ταιριάζει. Και αν περάσουμε το
$code
, ο κωδικός της εξαίρεσης πρέπει να είναι ο ίδιος.
Για παράδειγμα, αυτή η δοκιμή αποτυγχάνει επειδή το μήνυμα της εξαίρεσης δεν ταιριάζει:
Assert::exception(
fn() => throw new App\InvalidValueException('Zero value'),
App\InvalidValueException::class,
'Value is to low',
);
Το Assert::exception()
επιστρέφει μια πεταμένη εξαίρεση, οπότε
μπορείτε να ελέγξετε μια εμφωλευμένη εξαίρεση.
$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
παράγει τα αναμενόμενα σφάλματα
(δηλαδή προειδοποιήσεις, ειδοποιήσεις κ.λπ.). Ως $type
καθορίζουμε
μία από τις σταθερές E_...
, για παράδειγμα E_WARNING
. Και αν
περάσει το $message
, το μήνυμα σφάλματος πρέπει επίσης να ταιριάζει με το πρότυπο. Για παράδειγμα:
Assert::error(
fn() => $i++,
E_NOTICE,
'Undefined variable: i',
);
Εάν η επανάκληση παράγει περισσότερα σφάλματα, πρέπει να τα
περιμένουμε όλα με την ακριβή σειρά. Σε αυτή την περίπτωση περνάμε τον
πίνακα στο $type
:
Assert::error(function () {
$a++;
$b++;
}, [
[E_NOTICE, 'Undefined variable: a'],
[E_NOTICE, 'Undefined variable: b'],
]);
Εάν το $type
είναι όνομα κλάσης, αυτή η δήλωση
συμπεριφέρεται όπως το Assert::exception()
.
Assert::noError (callable $callable)
Ελέγχει ότι η συνάρτηση $callable
δεν πετάει καμία
προειδοποίηση/ειδοποίηση/σφάλμα ή εξαίρεση της PHP. Είναι χρήσιμη για
τον έλεγχο ενός κομματιού κώδικα όπου δεν υπάρχει άλλος ισχυρισμός.
Assert::match (string $pattern, $actual, ?string $description=null)
$actual
πρέπει να ταιριάζει με το $pattern
. Μπορούμε να
χρησιμοποιήσουμε δύο παραλλαγές προτύπων: κανονικές εκφράσεις ή
μπαλαντέρ.
Εάν περάσουμε μια κανονική έκφραση ως $pattern
, πρέπει να
χρησιμοποιήσουμε το ~
or #
για να την οριοθετήσουμε. Άλλα
διαχωριστικά δεν υποστηρίζονται. Για παράδειγμα, το test όπου το
$var
πρέπει να περιέχει μόνο δεκαεξαδικά ψηφία:
Assert::match('#^[0-9a-f]$#i', $var);
Η άλλη παραλλαγή είναι παρόμοια με τη σύγκριση συμβολοσειρών, αλλά
μπορούμε να χρησιμοποιήσουμε κάποια άγρια σύμβολα στο $pattern
:
%a%
ένα ή περισσότερα από οτιδήποτε εκτός από τους χαρακτήρες τέλους γραμμής%a?%
μηδέν ή περισσότερα από οτιδήποτε εκτός από τους χαρακτήρες τέλους γραμμής%A%
ένα ή περισσότερα από οτιδήποτε, συμπεριλαμβανομένων των χαρακτήρων τέλους γραμμής%A?%
μηδέν ή περισσότερα από οτιδήποτε, συμπεριλαμβανομένων των χαρακτήρων τέλους γραμμής%s%
ένας ή περισσότεροι χαρακτήρες λευκού διαστήματος εκτός από τους χαρακτήρες τέλους γραμμής%s?%
μηδέν ή περισσότεροι λευκοί χαρακτήρες εκτός από τους χαρακτήρες τέλους γραμμής%S%
ένας ή περισσότεροι χαρακτήρες εκτός από το λευκό διάστημα%S?%
μηδέν ή περισσότεροι χαρακτήρες εκτός από το λευκό διάστημα%c%
ένας μόνο χαρακτήρας οποιουδήποτε είδους (εκτός από το τέλος της γραμμής)%d%
ένα ή περισσότερα ψηφία%d?%
μηδέν ή περισσότερα ψηφία%i%
προσημασμένη ακέραια τιμή%f%
αριθμός κινητής υποδιαστολής%h%
ένα ή περισσότερα ψηφία HEX%w%
ένας ή περισσότεροι αλφαριθμητικοί χαρακτήρες%%
ένας χαρακτήρας %
Παραδείγματα:
# 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)
Ο ισχυρισμός είναι πανομοιότυπος με την Assert::match()
αλλά το μοτίβο φορτώνεται από το $file
. Είναι χρήσιμος για τον
έλεγχο πολύ μεγάλων συμβολοσειρών. Το αρχείο δοκιμής είναι
αναγνώσιμο.
Assert::fail (string $message, $actual=null, $expected=null)
Αυτός ο ισχυρισμός πάντα αποτυγχάνει. Είναι απλά πρακτικό. Μπορούμε να περάσουμε προαιρετικά αναμενόμενες και πραγματικές τιμές.
Προσδοκίες
Αν θέλουμε να συγκρίνουμε πιο σύνθετες δομές με μη σταθερά στοιχεία,
οι παραπάνω ισχυρισμοί μπορεί να μην είναι επαρκείς. Για παράδειγμα,
δοκιμάζουμε μια μέθοδο που δημιουργεί έναν νέο χρήστη και επιστρέφει
τα χαρακτηριστικά του ως πίνακα. Δεν γνωρίζουμε την τιμή
κατακερματισμού του κωδικού πρόσβασης, αλλά γνωρίζουμε ότι πρέπει να
είναι ένα δεκαεξαδικό αλφαριθμητικό. Και το μόνο πράγμα που γνωρίζουμε
για το επόμενο στοιχείο είναι ότι πρέπει να είναι ένα αντικείμενο
DateTime
.
Σε αυτές τις περιπτώσεις, μπορούμε να χρησιμοποιήσουμε το
Tester\Expect
μέσα στην παράμετρο $expected
των μεθόδων
Assert::equal()
και Assert::notEqual()
, το οποίο μπορεί να
χρησιμοποιηθεί για την εύκολη περιγραφή της δομής.
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'));
Με το Expect
, μπορούμε να κάνουμε σχεδόν τους ίδιους ισχυρισμούς
με το Assert
. Έτσι έχουμε μεθόδους όπως Expect::same()
,
Expect::match()
, Expect::count()
, κ.λπ. Επιπλέον, μπορούμε να τις
αλυσοδέσουμε όπως:
Expect::type(MyIterator::class)->andCount(5); # we expect MyIterator and items count is 5
Ή, μπορούμε να γράψουμε δικούς μας χειριστές ισχυρισμών.
Expect::that(function ($value) {
# return false if expectation fails
});
Διερεύνηση αποτυχημένων ισχυρισμών
Ο ελεγκτής δείχνει πού βρίσκεται το σφάλμα όταν ένας ισχυρισμός
αποτυγχάνει. Όταν συγκρίνουμε σύνθετες δομές, ο Tester δημιουργεί dumps των
συγκρινόμενων τιμών και τις αποθηκεύει στον κατάλογο output
. Για
παράδειγμα, όταν η φανταστική δοκιμή Arrays.recursive.phpt
αποτύχει, τα
dumps θα αποθηκευτούν ως εξής:
app/
└── tests/
├── output/
│ ├── Arrays.recursive.actual # actual value
│ └── Arrays.recursive.expected # expected value
│
└── Arrays.recursive.phpt # failing test
Μπορούμε να αλλάξουμε το όνομα του καταλόγου με
Tester\Dumper::$dumpDir
.