Quel est un bon moyen d'affirmer que deux tableaux d'objets sont égaux, lorsque l'ordre des éléments dans le tableau est sans importance, ou même sujet à changement?
132
Quel est un bon moyen d'affirmer que deux tableaux d'objets sont égaux, lorsque l'ordre des éléments dans le tableau est sans importance, ou même sujet à changement?
Réponses:
La façon la plus propre de faire cela serait d'étendre phpunit avec une nouvelle méthode d'assertion. Mais voici une idée pour un moyen plus simple pour le moment. Code non testé, veuillez vérifier:
Quelque part dans votre application:
Dans votre test:
la source
count(array_diff_assoc($b, $a))
également vérifier .Vous pouvez utiliser la méthode assertEqualsCanonicalizing qui a été ajoutée dans PHPUnit 7.5. Si vous comparez les tableaux en utilisant cette méthode, ces tableaux seront triés par le comparateur de tableaux PHPUnit lui-même.
Exemple de code:
Dans les anciennes versions de PHPUnit, vous pouvez utiliser un paramètre non documenté $ canonicalize de la méthode assertEquals . Si vous passez $ canonicalize = true , vous obtiendrez le même effet:
Code source du comparateur de tableaux à la dernière version de PHPUnit: https://github.com/sebastianbergmann/comparator/blob/master/src/ArrayComparator.php#L46
la source
$delta = 0.0, $maxDepth = 10, $canonicalize = true
pour passer des paramètres dans la fonction est trompeur - PHP ne prend pas en charge les arguments nommés. Ce que cela fait en fait est de définir ces trois variables, puis de transmettre immédiatement leurs valeurs à la fonction. Cela posera des problèmes si ces trois variables sont déjà définies dans la portée locale puisqu'elles seront écrasées.$this->assertEquals($array1, $array2, "\$canonicalize = true", 0.0, 10, true);
. Je pourrais utiliser 4 lignes au lieu de 1, mais je ne l'ai pas fait.$canonicalize
cela sera supprimé: github.com/sebastianbergmann/phpunit/issues/3342 etassertEqualsCanonicalizing()
le remplacera.Mon problème était que j'avais 2 tableaux (les clés de tableau ne sont pas pertinentes pour moi, juste les valeurs).
Par exemple, je voulais tester si
avait le même contenu (ordre non pertinent pour moi) que
J'ai donc utilisé array_diff .
Le résultat final était (si les tableaux sont égaux, la différence se traduira par un tableau vide). Veuillez noter que la différence est calculée dans les deux sens (Merci @beret, @GordonM)
Pour un message d'erreur plus détaillé (lors du débogage), vous pouvez également tester comme ceci (merci @ DenilsonSá):
Ancienne version avec des bugs à l'intérieur:
$ this-> assertEmpty (array_diff ($ array2, $ array1));la source
$array1
a plus de valeurs que$array2
, alors il renvoie un tableau vide même si les valeurs du tableau ne sont pas égales. Vous devriez également tester, que la taille du tableau est la même, pour être sûr.$a1 = [1,2,3,4,5]; $a2 = [1,3,5]; var_dump (array_diff ($a1, $a2)); var_dump (array_diff ($a2, $a1))
assertEmpty
n'imprimera pas le tableau s'il n'est pas vide, ce qui n'est pas pratique lors du débogage des tests. Je suggère d'utiliser:,$this->assertSame(array_diff($expected, $actual), array_diff($actual, $expected), $message);
car cela imprimera le message d'erreur le plus utile avec le minimum de code supplémentaire. Cela fonctionne parce que A \ B = B \ A ⇔ A \ B et B \ A sont vides ⇔ A = BArray to string conversion
message lorsque vous tenterez de convertir un tableau en chaîne. Un moyen de contourner ceimplode
Une autre possibilité:
la source
assertEquals
l'ordre n'a pas d'importance.$this->assertSame($exp, $arr);
qui ne comparaison similaire que$this->assertEquals(json_encode($exp), json_encode($arr));
seule différence est que nous ne devons pas utiliser json_encodeMéthode d'aide simple
Ou si vous avez besoin de plus d'informations de débogage lorsque les tableaux ne sont pas égaux
la source
Si le tableau est triable, je les trierais tous les deux avant de vérifier l'égalité. Sinon, je les convertirais en ensembles d'une sorte et les comparerais.
la source
En utilisant array_diff () :
Ou avec 2 assertions (plus faciles à lire):
la source
Même si vous ne vous souciez pas de la commande, il peut être plus facile d'en tenir compte:
Essayer:
la source
Nous utilisons la méthode wrapper suivante dans nos tests:
la source
Si les clés sont les mêmes mais dans le désordre, cela devrait le résoudre.
Il vous suffit de récupérer les clés dans le même ordre et de comparer les résultats.
la source
Les solutions données n'ont pas fait le travail pour moi parce que je voulais être capable de gérer des tableaux multidimensionnels et d'avoir un message clair sur ce qui est différent entre les deux tableaux.
Voici ma fonction
Alors pour l'utiliser
la source
J'ai écrit un code simple pour obtenir d'abord toutes les clés d'un tableau multidimensionnel:
Ensuite pour tester qu'ils étaient structurés de la même manière quel que soit l'ordre des clés:
HTH
la source
Si les valeurs ne sont que des int ou des chaînes, et pas de tableaux à plusieurs niveaux ...
Pourquoi ne pas simplement trier les tableaux, les convertir en chaîne ...
... puis comparez la chaîne:
la source
Si vous voulez tester uniquement les valeurs du tableau, vous pouvez faire:
la source
echo("<pre>"); print_r(array_values(array("size" => "XL", "color" => "gold"))); print_r(array_values(array("color" => "gold", "size" => "XL")));
Une autre option, comme si vous n'en aviez pas déjà assez, est de combiner
assertArraySubset
avecassertCount
pour faire votre affirmation. Donc, votre code ressemblerait à quelque chose comme.self::assertCount(EXPECTED_NUM_ELEMENT, $array); self::assertArraySubset(SUBSET, $array);
De cette façon, vous êtes indépendant de l'ordre tout en affirmant que tous vos éléments sont présents.
la source
assertArraySubset
l'ordre des index, cela ne fonctionnera pas. ie self :: assertArraySubset (['a'], ['b', 'a']) sera faux, car il[0 => 'a']
n'est pas à l'intérieur[0 => 'b', 1 => 'a']
assertEquals
gère déjà cela si les clés ne sont pas dans le même ordre. Je viens de le tester.