Qual é uma boa maneira de afirmar que duas matrizes de objetos são iguais, quando a ordem dos elementos na matriz não é importante ou está sujeita a alterações?
php
unit-testing
phpunit
assert
koen
fonte
fonte
Respostas:
A maneira mais limpa de fazer isso seria estender o phpunit com um novo método de asserção. Mas aqui está uma idéia para uma maneira mais simples por enquanto. Código não testado, verifique:
Em algum lugar do seu aplicativo:
No seu teste:
fonte
count(array_diff_assoc($b, $a))
também.Você pode usar o método assertEqualsCanonicalizing que foi adicionado no PHPUnit 7.5. Se você comparar as matrizes usando esse método, essas matrizes serão classificadas pelo próprio comparador de matrizes PHPUnit.
Exemplo de código:
Nas versões mais antigas do PHPUnit, você pode usar um parâmetro não documentado, $ canonicalize of assertEquals . Se você passar $ canonicalize = true , obterá o mesmo efeito:
Código-fonte do comparador de matrizes na versão mais recente do PHPUnit: https://github.com/sebastianbergmann/comparator/blob/master/src/ArrayComparator.php#L46
fonte
$delta = 0.0, $maxDepth = 10, $canonicalize = true
para passar parâmetros para a função é enganoso - o PHP não suporta argumentos nomeados. O que isso realmente está fazendo é definir essas três variáveis e passar imediatamente seus valores para a função. Isso causará problemas se essas três variáveis já estiverem definidas no escopo local, pois serão substituídas.$this->assertEquals($array1, $array2, "\$canonicalize = true", 0.0, 10, true);
. Eu poderia usar 4 linhas em vez de 1, mas não fiz isso.$canonicalize
será removido: github.com/sebastianbergmann/phpunit/issues/3342 eassertEqualsCanonicalizing()
o substituirá.Meu problema era que eu tinha 2 matrizes (chaves de matriz não são relevantes para mim, apenas os valores).
Por exemplo, eu queria testar se
tinha o mesmo conteúdo (pedido não relevante para mim) que
Então, eu usei array_diff .
O resultado final foi (se as matrizes forem iguais, a diferença resultará em uma matriz vazia). Observe que a diferença é calculada nos dois sentidos (Obrigado @beret, @GordonM)
Para uma mensagem de erro mais detalhada (durante a depuração), você também pode testar desta forma (obrigado @ DenilsonSá):
Versão antiga com erros dentro:
$ this-> assertEmpty (array_diff ($ array2, $ array1));fonte
$array1
tiver mais valores que$array2
, retornará uma matriz vazia, mesmo que os valores da matriz não sejam iguais. Você também deve testar se o tamanho da matriz é o mesmo, para ter certeza.$a1 = [1,2,3,4,5]; $a2 = [1,3,5]; var_dump (array_diff ($a1, $a2)); var_dump (array_diff ($a2, $a1))
assertEmpty
não imprimirá a matriz se não estiver vazia, o que é inconveniente durante a depuração de testes. Eu sugiro usar:,$this->assertSame(array_diff($expected, $actual), array_diff($actual, $expected), $message);
pois isso imprimirá a mensagem de erro mais útil com o mínimo de código extra. Isto funciona porque A \ B = B \ Uma ⇔ A \ B e B \ A são vazio ⇔ A = BArray to string conversion
mensagem ao tentar converter uma matriz em uma string. Uma maneira de contornar isso é usandoimplode
Outra possibilidade:
fonte
assertEquals
o pedido não importa.$this->assertSame($exp, $arr);
o que faz comparação semelhante como$this->assertEquals(json_encode($exp), json_encode($arr));
única diferença é que não tem que usar json_encodeMétodo auxiliar simples
Ou se você precisar de mais informações de depuração quando matrizes não forem iguais
fonte
Se a matriz for classificável, eu os classificaria antes de verificar a igualdade. Caso contrário, eu os converteria em conjuntos de algum tipo e os compararia.
fonte
Usando array_diff () :
Ou com 2 afirmações (mais fáceis de ler):
fonte
Mesmo que você não se importe com o pedido, pode ser mais fácil levar isso em consideração:
Experimentar:
fonte
Usamos o seguinte método de invólucro em nossos testes:
fonte
Se as chaves forem as mesmas, mas fora de ordem, isso deve resolver o problema.
Você só precisa obter as chaves na mesma ordem e comparar os resultados.
fonte
As soluções fornecidas não funcionaram para mim porque eu queria poder lidar com uma matriz multidimensional e ter uma mensagem clara do que é diferente entre as duas matrizes.
Aqui está a minha função
Então para usá-lo
fonte
Eu escrevi um código simples para primeiro obter todas as chaves de uma matriz multidimensional:
Depois, para testar se eles foram estruturados da mesma maneira, independentemente da ordem das chaves:
HTH
fonte
Se os valores são apenas int ou strings, e nenhuma matriz de vários níveis ....
Por que não apenas classificar as matrizes, convertê-las em string ...
... e depois compare a string:
fonte
Se você deseja testar apenas os valores da matriz, pode fazer:
fonte
echo("<pre>"); print_r(array_values(array("size" => "XL", "color" => "gold"))); print_r(array_values(array("color" => "gold", "size" => "XL")));
Outra opção, como se você já não tivesse o suficiente, é combinar
assertArraySubset
combinado comassertCount
para fazer sua afirmação. Portanto, seu código seria algo parecido.self::assertCount(EXPECTED_NUM_ELEMENT, $array); self::assertArraySubset(SUBSET, $array);
Dessa forma, você é independente da ordem, mas ainda afirma que todos os seus elementos estão presentes.
fonte
assertArraySubset
ordem dos índices, importa para que não funcione. ou seja self :: assertArraySubset ([ 'a'], [ 'b', 'a']) será falso, porque[0 => 'a']
não está dentro[0 => 'b', 1 => 'a']
assertEquals
já lida com isso se as chaves não estiverem na mesma ordem. Eu apenas testei.