¿Cuál es una buena manera de afirmar que dos conjuntos de objetos son iguales, cuando el orden de los elementos en el conjunto no es importante, o incluso está sujeto a cambios?
php
unit-testing
phpunit
assert
koen
fuente
fuente
Respuestas:
La forma más limpia de hacer esto sería extender phpunit con un nuevo método de afirmación. Pero aquí hay una idea de una manera más simple por ahora. Código no probado, verifique:
En algún lugar de tu aplicación:
En tu prueba:
fuente
count(array_diff_assoc($b, $a))
también.Puede usar el método ClaimEqualsCanonicalizing que se agregó en PHPUnit 7.5. Si compara las matrices utilizando este método, estas matrices se ordenarán por el comparador de matrices PHPUnit.
Ejemplo de código:
En versiones anteriores de PHPUnit, puede usar un parámetro no documentado $ canonicalize del método afirmarEquals . Si pasa $ canonicalize = true , obtendrá el mismo efecto:
Código fuente del comparador de matrices en la última versión de PHPUnit: https://github.com/sebastianbergmann/comparator/blob/master/src/ArrayComparator.php#L46
fuente
$delta = 0.0, $maxDepth = 10, $canonicalize = true
pasar parámetros a la función es engañoso: PHP no admite argumentos con nombre. Lo que esto realmente está haciendo es establecer esas tres variables, luego pasar inmediatamente sus valores a la función. Esto causará problemas si esas tres variables ya están definidas en el ámbito local, ya que se sobrescribirán.$this->assertEquals($array1, $array2, "\$canonicalize = true", 0.0, 10, true);
. Podría usar 4 líneas en lugar de 1, pero no hice eso.$canonicalize
se eliminará: github.com/sebastianbergmann/phpunit/issues/3342 yassertEqualsCanonicalizing()
lo reemplazará.Mi problema era que tenía 2 matrices (las claves de matriz no son relevantes para mí, solo los valores).
Por ejemplo, quería probar si
tenía el mismo contenido (orden no relevante para mí) como
Así que he usado array_diff .
El resultado final fue (si las matrices son iguales, la diferencia dará como resultado una matriz vacía). Tenga en cuenta que la diferencia se calcula en ambos sentidos (Gracias @beret, @GordonM)
Para un mensaje de error más detallado (durante la depuración), también puede probar de esta manera (gracias @ DenilsonSá):
Versión antigua con errores dentro:
$ this-> afirmeEmpty (array_diff ($ array2, $ array1));fuente
$array1
tiene más valores que$array2
, entonces devuelve una matriz vacía aunque los valores de la matriz no sean iguales. También debe probar, ese tamaño de matriz es el mismo, para estar seguro.$a1 = [1,2,3,4,5]; $a2 = [1,3,5]; var_dump (array_diff ($a1, $a2)); var_dump (array_diff ($a2, $a1))
assertEmpty
no imprimirá la matriz si no está vacía, lo cual es inconveniente al depurar las pruebas. Sugeriría usar:$this->assertSame(array_diff($expected, $actual), array_diff($actual, $expected), $message);
ya que esto imprimirá el mensaje de error más útil con el mínimo de código adicional. Esto funciona porque A \ B = B \ A ⇔ A \ B y B \ A están vacías ⇔ A = BArray to string conversion
mensaje cuando intente convertir una matriz en una cadena. Una forma de evitar esto es usandoimplode
Otra posibilidad:
fuente
assertEquals
el orden no importa.$this->assertSame($exp, $arr);
una comparación similar, ya que la$this->assertEquals(json_encode($exp), json_encode($arr));
única diferencia es que no tenemos que usar json_encodeMétodo de ayuda simple
O si necesita más información de depuración cuando las matrices no son iguales
fuente
Si la matriz es ordenable, los ordenaría a ambos antes de verificar la igualdad. Si no, los convertiría en conjuntos de algún tipo y los compararía.
fuente
Usando array_diff () :
O con 2 afirmaciones (más fácil de leer):
fuente
Aunque no le importa el pedido, puede ser más fácil tenerlo en cuenta:
Tratar:
fuente
Utilizamos el siguiente método de envoltura en nuestras Pruebas:
fuente
Si las claves son las mismas pero fuera de servicio, esto debería resolverlo.
Solo tiene que obtener las claves en el mismo orden y comparar los resultados.
fuente
Las soluciones dadas no hicieron el trabajo por mí porque quería ser capaz de manejar una matriz multidimensional y tener un mensaje claro de lo que es diferente entre las dos matrices.
Aqui esta mi funcion
Entonces para usarlo
fuente
Escribí un código simple para obtener primero todas las claves de una matriz multidimensional:
Luego, para comprobar que estaban estructurados de la misma manera, independientemente del orden de las teclas:
HTH
fuente
Si los valores son solo int o cadenas, y no hay matrices de niveles múltiples ...
¿Por qué no simplemente ordenar las matrices, convertirlas en cadenas ...
... y luego compara la cadena:
fuente
Si desea probar solo los valores de la matriz que puede hacer:
fuente
echo("<pre>"); print_r(array_values(array("size" => "XL", "color" => "gold"))); print_r(array_values(array("color" => "gold", "size" => "XL")));
Otra opción, como si no tuviera ya suficiente, es combinar
assertArraySubset
combinado conassertCount
para hacer su afirmación. Entonces, su código se vería algo así.self::assertCount(EXPECTED_NUM_ELEMENT, $array); self::assertArraySubset(SUBSET, $array);
De esta manera, usted es independiente del orden pero aún así afirma que todos sus elementos están presentes.
fuente
assertArraySubset
el orden de los índices importa, por lo que no funcionará. es decir, self :: afirmarArraySubset (['a'], ['b', 'a']) será falso, porque[0 => 'a']
no está adentro[0 => 'b', 1 => 'a']
assertEquals
ya lo maneja si las claves no están en el mismo orden. Acabo de probarlo.