Как правильно утверждать, что два массива объектов равны, когда порядок элементов в массиве не важен или даже может быть изменен?
php
unit-testing
phpunit
assert
Koen
источник
источник
Ответы:
Самый простой способ сделать это - расширить phpunit новым методом утверждения. Но пока что есть идея более простого способа. Непроверенный код, проверьте:
Где-то в вашем приложении:
В вашем тесте:
источник
count(array_diff_assoc($b, $a))
.Вы можете использовать метод assertEqualsCanonicalizing, который был добавлен в PHPUnit 7.5. Если вы сравните массивы с помощью этого метода, эти массивы будут отсортированы самим компаратором массивов PHPUnit.
Пример кода:
В более старых версиях PHPUnit вы можете использовать недокументированный параметр $ canonicalize метода assertEquals . Если вы передадите $ canonicalize = true , вы получите тот же эффект:
Исходный код компаратора массивов в последней версии PHPUnit: https://github.com/sebastianbergmann/comparator/blob/master/src/ArrayComparator.php#L46
источник
$delta = 0.0, $maxDepth = 10, $canonicalize = true
для передачи параметров в функцию вводит в заблуждение - PHP не поддерживает именованные аргументы. На самом деле это устанавливает эти три переменные, а затем немедленно передает их значения функции. Это вызовет проблемы, если эти три переменные уже определены в локальной области, поскольку они будут перезаписаны.$this->assertEquals($array1, $array2, "\$canonicalize = true", 0.0, 10, true);
. Я мог использовать 4 строки вместо 1, но я этого не делал.$canonicalize
будет удалено: github.com/sebastianbergmann/phpunit/issues/3342 иassertEqualsCanonicalizing()
заменит его.Моя проблема заключалась в том, что у меня было 2 массива (ключи массива для меня не актуальны, только значения).
Например, я хотел проверить, если
имел такое же содержание (порядок не важен для меня), что и
Итак, я использовал array_diff .
Окончательный результат был (если массивы равны, разница приведет к пустому массиву). Обратите внимание, что разница вычисляется в обоих направлениях (спасибо @beret, @GordonM)
Для получения более подробного сообщения об ошибке (во время отладки) вы также можете проверить это (спасибо @ DenilsonSá):
Старая версия с ошибками внутри:
$ this-> assertEmpty (array_diff ($ array2, $ array1));источник
$array1
имеется больше значений, чем$array2
, то он возвращает пустой массив, даже если значения массива не равны. Вы также должны проверить, что размер массива такой же, чтобы быть уверенным.$a1 = [1,2,3,4,5]; $a2 = [1,3,5]; var_dump (array_diff ($a1, $a2)); var_dump (array_diff ($a2, $a1))
assertEmpty
не будет печатать массив, если он не пустой, что неудобно при отладке тестов. Я бы посоветовал использовать:, так$this->assertSame(array_diff($expected, $actual), array_diff($actual, $expected), $message);
как это напечатает наиболее полезное сообщение об ошибке с минимумом дополнительного кода. Это работает, потому что A \ B = B \ A ⇔ A \ B и B \ A пустые ⇔ A = BArray to string conversion
сообщение, когда попытаетесь преобразовать массив в строку. Чтобы обойти это, используйтеimplode
Еще одна возможность:
источник
assertEquals
порядка значения не имеет.$this->assertSame($exp, $arr);
который выполняет аналогичное сравнение, с той$this->assertEquals(json_encode($exp), json_encode($arr));
лишь разницей, что нам не нужно использовать json_encodeПростой вспомогательный метод
Или, если вам нужна дополнительная информация об отладке, когда массивы не равны
источник
Если массив можно сортировать, я бы отсортировал их обоих, прежде чем проверять равенство. Если нет, я бы преобразовал их в какие-то наборы и сравнил их.
источник
Использование array_diff () :
Или с двумя утверждениями (легче читать):
источник
Даже если вас не волнует порядок, может быть проще это учесть:
Пытаться:
источник
В наших тестах мы используем следующий метод-оболочку:
источник
Если ключи такие же, но вышли из строя, это должно решить проблему.
Вам просто нужно получить ключи в том же порядке и сравнить результаты.
источник
Данные решения не помогли мне, потому что я хотел иметь возможность обрабатывать многомерный массив и иметь четкое представление о различиях между двумя массивами.
Вот моя функция
Затем использовать это
источник
Я написал простой код, чтобы сначала получить все ключи из многомерного массива:
Затем, чтобы проверить, что они были структурированы одинаково независимо от порядка ключей:
НТН
источник
Если значения представляют собой просто int или строки, а не многоуровневые массивы ....
Почему бы просто не отсортировать массивы, преобразовать их в строку ...
... а затем сравните строку:
источник
Если вы хотите проверить только значения массива, вы можете:
источник
echo("<pre>"); print_r(array_values(array("size" => "XL", "color" => "gold"))); print_r(array_values(array("color" => "gold", "size" => "XL")));
Другой вариант, как если бы вам уже не хватало, - это объединить
assertArraySubset
с,assertCount
чтобы сделать ваше утверждение. Итак, ваш код будет выглядеть примерно так.self::assertCount(EXPECTED_NUM_ELEMENT, $array); self::assertArraySubset(SUBSET, $array);
Таким образом, вы независимы от порядка, но при этом утверждаете, что все ваши элементы присутствуют.
источник
assertArraySubset
порядке индексов важно , чтобы она не будет работать. т.е. self :: assertArraySubset (['a'], ['b', 'a']) будет ложным, потому что[0 => 'a']
не внутри[0 => 'b', 1 => 'a']
assertEquals
уже обрабатывает это, если ключи не в том же порядке. Я только что это протестировал.