PHPUnit: 두 어레이가 동일하지만 요소의 순서는 중요하지 않습니다.
배열 내 요소의 순서가 중요하지 않거나 변경될 수 있는 경우 두 개체의 배열이 동일하다고 주장하는 좋은 방법은 무엇입니까?
PHPUnit 7.5에 추가된 assertEqualsCanonicalizing 메서드를 사용할 수 있습니다.이 방법을 사용하여 어레이를 비교할 경우 이러한 어레이는 PHPUnit 어레이 비교기 자체별로 정렬됩니다.
코드 예:
class ArraysTest extends \PHPUnit\Framework\TestCase
{
public function testEquality()
{
$obj1 = $this->getObject(1);
$obj2 = $this->getObject(2);
$obj3 = $this->getObject(3);
$array1 = [$obj1, $obj2, $obj3];
$array2 = [$obj2, $obj1, $obj3];
// Pass
$this->assertEqualsCanonicalizing($array1, $array2);
// Fail
$this->assertEquals($array1, $array2);
}
private function getObject($value)
{
$result = new \stdClass();
$result->property = $value;
return $result;
}
}
이전 버전의 PHPUnit에서는 문서화되어 있지 않은 파라미터 $canonicalize of assertEquals 메서드를 사용할 수 있습니다.$sysize = true를 통과하면 다음과 같은 효과가 나타납니다.
class ArraysTest extends PHPUnit_Framework_TestCase
{
public function testEquality()
{
$obj1 = $this->getObject(1);
$obj2 = $this->getObject(2);
$obj3 = $this->getObject(3);
$array1 = [$obj1, $obj2, $obj3];
$array2 = [$obj2, $obj1, $obj3];
// Pass
$this->assertEquals($array1, $array2, "\$canonicalize = true", 0.0, 10, true);
// Fail
$this->assertEquals($array1, $array2, "Default behaviour");
}
private function getObject($value)
{
$result = new stdclass();
$result->property = $value;
return $result;
}
}
최신 버전의 PHPUnit 어레이 비교 소스 코드:https://github.com/sebastianbergmann/comparator/blob/master/src/ArrayComparator.php#L46
이를 위한 가장 깨끗한 방법은 새로운 어설션 메서드로 phpunit을 확장하는 것입니다.하지만 지금으로서는 좀 더 간단한 방법이 있다.테스트되지 않은 코드입니다. 확인하십시오.
앱 내 어딘가에서:
/**
* Determine if two associative arrays are similar
*
* Both arrays must have the same indexes with identical values
* without respect to key ordering
*
* @param array $a
* @param array $b
* @return bool
*/
function arrays_are_similar($a, $b) {
// if the indexes don't match, return immediately
if (count(array_diff_assoc($a, $b))) {
return false;
}
// we know that the indexes, but maybe not values, match.
// compare the values between the two arrays
foreach($a as $k => $v) {
if ($v !== $b[$k]) {
return false;
}
}
// we have identical indexes, and no unequal values
return true;
}
테스트 시:
$this->assertTrue(arrays_are_similar($foo, $bar));
문제는 2개의 어레이가 있다는 것이었습니다(어레이 키는 중요하지 않고 값만 상관없습니다).
예를 들어, 나는 테스트하고 싶었다.
$expected = array("0" => "green", "2" => "red", "5" => "blue", "9" => "pink");
(나와는 무관한 주문)과 같은 내용을 가지고 있다.
$actual = array("0" => "pink", "1" => "green", "3" => "yellow", "red", "blue");
array_diff 를 사용하고 있습니다.
최종 결과는 다음과 같습니다(어레이가 같으면 그 차이로 인해 빈 어레이가 됩니다).차이는 양쪽 모두 계산됩니다(Thanks @beret, @GordonM).
$this->assertEmpty(array_merge(array_diff($expected, $actual), array_diff($actual, $expected)));
자세한 오류 메시지(디버깅 중)에 대해서는 다음과 같이 테스트할 수도 있습니다(@Denilson 감사합니다).Sa):
$this->assertSame(array_diff($expected, $actual), array_diff($actual, $expected));
내부에 버그가 있는 이전 버전:
$this->assert Empty(array_diff($array2, $array1));
또 하나의 가능성:
- 양쪽 어레이 정렬
- 문자열로 변환
- 두 문자열이 동일하다고 주장합니다.
$arr = array(23, 42, 108);
$exp = array(42, 23, 108);
sort($arr);
sort($exp);
$this->assertEquals(json_encode($exp), json_encode($arr));
간단한 도우미 방법
protected function assertEqualsArrays($expected, $actual, $message) {
$this->assertTrue(count($expected) == count(array_intersect($expected, $actual)), $message);
}
또는 어레이가 동일하지 않을 때 더 많은 디버깅 정보가 필요한 경우
protected function assertEqualsArrays($expected, $actual, $message) {
sort($expected);
sort($actual);
$this->assertEquals($expected, $actual, $message);
}
배열이 정렬 가능한 경우 동등성을 확인하기 전에 둘 다 정렬합니다.만약 그렇지 않다면, 나는 그것들을 일종의 세트로 변환하고 그것들을 비교할 것이다.
키가 동일하지만 고장난 경우 해결됩니다.
같은 순서로 키를 가져와 결과를 비교하기만 하면 됩니다.
/**
* Assert Array structures are the same
*
* @param array $expected Expected Array
* @param array $actual Actual Array
* @param string|null $msg Message to output on failure
*
* @return bool
*/
public function assertArrayStructure($expected, $actual, $msg = '') {
ksort($expected);
ksort($actual);
$this->assertSame($expected, $actual, $msg);
}
주문에 관심이 없더라도 이를 고려하는 것이 더 쉬울 수 있습니다.
시험:
asort($foo);
asort($bar);
$this->assertEquals($foo, $bar);
array_diff() 사용:
$a1 = array(1, 2, 3);
$a2 = array(3, 2, 1);
// error when arrays don't have the same elements (order doesn't matter):
$this->assertEquals(0, count(array_diff($a1, $a2)) + count(array_diff($a2, $a1)));
또는 2개의 어설트(읽기 쉬운 것):
// error when arrays don't have the same elements (order doesn't matter):
$this->assertEquals(0, count(array_diff($a1, $a2)));
$this->assertEquals(0, count(array_diff($a2, $a1)));
테스트에서는 다음 래퍼 방법을 사용합니다.
/**
* Assert that two arrays are equal. This helper method will sort the two arrays before comparing them if
* necessary. This only works for one-dimensional arrays, if you need multi-dimension support, you will
* have to iterate through the dimensions yourself.
* @param array $expected the expected array
* @param array $actual the actual array
* @param bool $regard_order whether or not array elements may appear in any order, default is false
* @param bool $check_keys whether or not to check the keys in an associative array
*/
protected function assertArraysEqual(array $expected, array $actual, $regard_order = false, $check_keys = true) {
// check length first
$this->assertEquals(count($expected), count($actual), 'Failed to assert that two arrays have the same length.');
// sort arrays if order is irrelevant
if (!$regard_order) {
if ($check_keys) {
$this->assertTrue(ksort($expected), 'Failed to sort array.');
$this->assertTrue(ksort($actual), 'Failed to sort array.');
} else {
$this->assertTrue(sort($expected), 'Failed to sort array.');
$this->assertTrue(sort($actual), 'Failed to sort array.');
}
}
$this->assertEquals($expected, $actual);
}
저는 다차원 어레이를 처리할 수 있고 두 어레이의 차이점을 명확하게 전달하고 싶었기 때문에 주어진 솔루션이 도움이 되지 않았습니다.
이것이 나의 기능이다.
public function assertArrayEquals($array1, $array2, $rootPath = array())
{
foreach ($array1 as $key => $value)
{
$this->assertArrayHasKey($key, $array2);
if (isset($array2[$key]))
{
$keyPath = $rootPath;
$keyPath[] = $key;
if (is_array($value))
{
$this->assertArrayEquals($value, $array2[$key], $keyPath);
}
else
{
$this->assertEquals($value, $array2[$key], "Failed asserting that `".$array2[$key]."` matches expected `$value` for path `".implode(" > ", $keyPath)."`.");
}
}
}
}
그럼 사용하기 위해서
$this->assertArrayEquals($array1, $array2, array("/"));
먼저 다차원 배열에서 모든 키를 얻기 위한 간단한 코드를 작성했습니다.
/**
* Returns all keys from arrays with any number of levels
* @param array
* @return array
*/
protected function getAllArrayKeys($array)
{
$keys = array();
foreach ($array as $key => $element) {
$keys[] = $key;
if (is_array($array[$key])) {
$keys = array_merge($keys, $this->getAllArrayKeys($array[$key]));
}
}
return $keys;
}
그런 다음 키 순서에 관계없이 동일한 구조로 구성되었는지 테스트합니다.
$expectedKeys = $this->getAllArrayKeys($expectedData);
$actualKeys = $this->getAllArrayKeys($actualData);
$this->assertEmpty(array_diff($expectedKeys, $actualKeys));
HTH
값이 int 또는 string일 뿐이고 다중 수준 배열이 없는 경우...
어레이를 정렬하고 문자열로 변환하면...
$mapping = implode(',', array_sort($myArray));
$list = implode(',', array_sort($myExpectedArray));
...그리고 문자열을 비교합니다.
$this->assertEquals($myExpectedArray, $myArray);
어레이 값만 테스트하려면 다음 작업을 수행합니다.
$this->assertEquals(array_values($arrayOne), array_values($arrayTwo));
다른 아직처럼 '먹다'와 '먹다'를 조합하는 입니다.assertArraySubset
combined와 assertCount
당신의 주장을 하기 위해서요.그래서, 당신의 코드는 이렇게 생겼을 것입니다.
self::assertCount(EXPECTED_NUM_ELEMENT, $array); self::assertArraySubset(SUBSET, $array);
이렇게 하면 독립적이면서도 모든 요소가 존재한다고 주장할 수 있습니다.
언급URL : https://stackoverflow.com/questions/3838288/phpunit-assert-two-arrays-are-equal-but-order-of-elements-not-important
'programing' 카테고리의 다른 글
JavaScript를 사용한 이미지 프리로드 (0) | 2023.01.31 |
---|---|
SELECT 내에서 여러 CASE 콜을 심플화 (0) | 2023.01.31 |
SoapClient 클래스를 사용하여 PHP SOAP 호출을 발신하는 방법 (0) | 2023.01.31 |
SOAP 메시지와 WSDL의 차이점 (0) | 2023.01.31 |
en_UK는 부정한 로케일입니까? (0) | 2023.01.31 |