Was ist ein guter Weg, um zu behaupten, dass zwei Arrays von Objekten gleich sind, wenn die Reihenfolge der Elemente im Array unwichtig ist oder sich sogar ändern kann?
php
unit-testing
phpunit
assert
koen
quelle
quelle
Antworten:
Der sauberste Weg, dies zu tun, wäre, phpunit mit einer neuen Assertionsmethode zu erweitern. Aber hier ist eine Idee für einen einfacheren Weg. Ungetesteter Code, bitte überprüfen Sie:
Irgendwo in Ihrer App:
In Ihrem Test:
quelle
count(array_diff_assoc($b, $a))
.Sie können die in PHPUnit 7.5 hinzugefügte assertEqualsCanonicalizing- Methode verwenden. Wenn Sie die Arrays mit dieser Methode vergleichen, werden diese Arrays nach dem PHPUnit-Arrays-Komparator selbst sortiert.
Codebeispiel:
In älteren Versionen von PHPUnit können Sie einen undokumentierten Parameter $ canonicalize der assertEquals- Methode verwenden. Wenn Sie $ canonicalize = true übergeben , erhalten Sie den gleichen Effekt:
Arrays-Komparator-Quellcode in der neuesten Version von PHPUnit: https://github.com/sebastianbergmann/comparator/blob/master/src/ArrayComparator.php#L46
quelle
$delta = 0.0, $maxDepth = 10, $canonicalize = true
Übergabe von Parametern an die Funktion ist irreführend - PHP unterstützt keine benannten Argumente. Dabei werden diese drei Variablen festgelegt und ihre Werte sofort an die Funktion übergeben. Dies führt zu Problemen, wenn diese drei Variablen bereits im lokalen Bereich definiert sind, da sie überschrieben werden.$this->assertEquals($array1, $array2, "\$canonicalize = true", 0.0, 10, true);
. Ich könnte 4 Zeilen anstelle von 1 verwenden, aber das habe ich nicht getan.$canonicalize
dass entfernt wird: github.com/sebastianbergmann/phpunit/issues/3342 undassertEqualsCanonicalizing()
ersetzt.Mein Problem war, dass ich 2 Arrays hatte (Array-Schlüssel sind für mich nicht relevant, nur die Werte).
Zum Beispiel wollte ich testen, ob
hatte den gleichen Inhalt (Reihenfolge für mich nicht relevant) wie
Also habe ich array_diff verwendet .
Das Endergebnis war (wenn die Arrays gleich sind, führt die Differenz zu einem leeren Array). Bitte beachten Sie, dass der Unterschied in beide Richtungen berechnet wird (Danke @beret, @GordonM).
Für eine detailliertere Fehlermeldung (beim Debuggen) können Sie auch wie folgt testen (danke @ DenilsonSá):
Alte Version mit Fehlern im Inneren:
$ this-> assertEmpty (array_diff ($ array2, $ array1));quelle
$array1
mehr Werte als vorhanden sind$array2
, ein leeres Array zurückgegeben wird, obwohl die Array-Werte nicht gleich sind. Sie sollten auch testen, ob die Arraygröße gleich ist, um sicherzugehen.$a1 = [1,2,3,4,5]; $a2 = [1,3,5]; var_dump (array_diff ($a1, $a2)); var_dump (array_diff ($a2, $a1))
assertEmpty
druckt das Array nicht, wenn es nicht leer ist, was beim Debuggen von Tests unpraktisch ist. Ich würde vorschlagen,: zu verwenden$this->assertSame(array_diff($expected, $actual), array_diff($actual, $expected), $message);
, da dies die nützlichste Fehlermeldung mit einem Minimum an zusätzlichem Code druckt. Dies funktioniert, weil A \ B = B \ A ⇔ A \ B und B \ A leer sind ⇔ A = BArray to string conversion
Nachricht, wenn Sie versuchen, ein Array in eine Zeichenfolge umzuwandeln . Eine Möglichkeit, dies zuimplode
Eine andere Möglichkeit:
quelle
assertEquals
die Bestellung spielt das keine Rolle.$this->assertSame($exp, $arr);
ähnlichen Vergleich verwenden, da der$this->assertEquals(json_encode($exp), json_encode($arr));
einzige Unterschied darin besteht, dass wir json_encodeEinfache Hilfsmethode
Oder wenn Sie mehr Debug-Informationen benötigen, wenn Arrays nicht gleich sind
quelle
Wenn das Array sortierbar ist, würde ich beide sortieren, bevor ich die Gleichheit überprüfe. Wenn nicht, würde ich sie in Sätze umwandeln und diese vergleichen.
quelle
Verwenden von array_diff () :
Oder mit 2 Behauptungen (leichter zu lesen):
quelle
Auch wenn Sie sich nicht für die Bestellung interessieren, ist es möglicherweise einfacher, dies zu berücksichtigen:
Versuchen:
quelle
In unseren Tests verwenden wir die folgende Wrapper-Methode:
quelle
Wenn die Schlüssel gleich, aber nicht in Ordnung sind, sollte dies das Problem lösen.
Sie müssen nur die Schlüssel in derselben Reihenfolge erhalten und die Ergebnisse vergleichen.
quelle
Die angegebenen Lösungen haben für mich nicht funktioniert, weil ich in der Lage sein wollte, mehrdimensionale Arrays zu verarbeiten und eine klare Botschaft darüber zu erhalten, was zwischen den beiden Arrays unterschiedlich ist.
Hier ist meine Funktion
Dann, um es zu benutzen
quelle
Ich habe einen einfachen Code geschrieben, um zuerst alle Schlüssel aus einem mehrdimensionalen Array zu erhalten:
Um dann zu testen, ob sie unabhängig von der Reihenfolge der Schlüssel gleich aufgebaut sind:
HTH
quelle
Wenn die Werte nur int oder Strings sind und keine Arrays mit mehreren Ebenen ....
Warum nicht einfach die Arrays sortieren, sie in einen String konvertieren ...
... und dann String vergleichen:
quelle
Wenn Sie nur die Werte des Arrays testen möchten, können Sie Folgendes tun:
quelle
echo("<pre>"); print_r(array_values(array("size" => "XL", "color" => "gold"))); print_r(array_values(array("color" => "gold", "size" => "XL")));
Eine andere Möglichkeit, als ob Sie noch nicht genug hätten, ist die
assertArraySubset
Kombination mitassertCount
, um Ihre Behauptung aufzustellen. Ihr Code würde also ungefähr so aussehen.self::assertCount(EXPECTED_NUM_ELEMENT, $array); self::assertArraySubset(SUBSET, $array);
Auf diese Weise sind Sie auftragsunabhängig und behaupten dennoch, dass alle Ihre Elemente vorhanden sind.
quelle
assertArraySubset
der Reihenfolge der Indizes ist es wichtig, dass es nicht funktioniert. dh self :: assertArraySubset (['a'], ['b', 'a']) wird falsch sein, weil[0 => 'a']
es nicht drinnen ist[0 => 'b', 1 => 'a']
assertEquals
bereits erledigt, wenn die Schlüssel nicht in derselben Reihenfolge sind. Ich habe es gerade getestet.