Lor*_*ori 8 php arrays phpunit
我需要一个PHP函数,可以断言两个数组是相同的,而忽略指定键集的值(只有值,键必须匹配).
实际上,数组必须具有相同的结构,但可以忽略某些值.
例如,考虑以下两个数组:
Array
(
[0] => Array
(
[id] => 0
[title] => Book1 Title
[creationDate] => 2013-01-13 17:01:07
[pageCount] => 0
)
)
Array
(
[0] => Array
(
[id] => 1
[title] => Book1 Title
[creationDate] => 2013-01-13 17:01:07
[pageCount] => 0
)
)
Run Code Online (Sandbox Code Playgroud)
如果我们忽略键的值,它们就是一样的id.
我还想考虑嵌套数组的可能性:
Array
(
[0] => Array
(
[id] => 0
[title] => Book1 Title
[creationDate] => 2013-01-13 17:01:07
[pageCount] => 0
)
[1] => Array
(
[id] => 0
[title] => Book2 Title
[creationDate] => 2013-01-13 18:01:07
[pageCount] => 0
)
)
Array
(
[0] => Array
(
[id] => 2
[title] => Book1 Title
[creationDate] => 2013-01-13 17:01:07
[pageCount] => 0
)
[1] => Array
(
[id] => 3
[title] => Book2 Title
[creationDate] => 2013-01-13 18:01:07
[pageCount] => 0
)
)
Run Code Online (Sandbox Code Playgroud)
因为我需要它进行测试,所以我提出了以下扩展PHPUnit_Framework_TestCase并使用其断言函数的类:
class MyTestCase extends PHPUnit_Framework_TestCase
{
public static function assertArraysSame($expected, $actual, array $ignoreKeys = array())
{
self::doAssertArraysSame($expected, $actual, $ignoreKeys, 1);
}
private static function doAssertArraysSame($expected, $actual, array $ignoreKeys = array(), $depth, $maxDepth = 256)
{
self::assertNotEquals($depth, $maxDepth);
$depth++;
foreach ($expected as $key => $exp) {
// check they both have this key
self::assertArrayHasKey($key, $actual);
// check nested arrays
if (is_array($exp))
self::doAssertArraysSame($exp, $actual[$key], $ignoreKeys, $depth);
// check they have the same value unless the key is in the to-ignore list
else if (array_search($key, $ignoreKeys) === false)
self::assertSame($exp, $actual[$key]);
// remove the current elements
unset($expected[$key]);
unset($actual[$key]);
}
// check that the two arrays are both empty now, which means they had the same lenght
self::assertEmpty($expected);
self::assertEmpty($actual);
}
}
Run Code Online (Sandbox Code Playgroud)
doAssertArraysSame迭代遍历其中一个数组并递归断言两个数组具有相同的键.除非当前键位于要忽略的键列表中,否则它还会检查它们是否具有相同的值.
为了确保两个数组具有完全相同数量的元素,在迭代期间删除每个元素,并且在循环结束时,函数检查两个数组是否为空.
用法:
class MyTest extends MyTestCase
{
public function test_Books()
{
$a1 = array('id' => 1, 'title' => 'the title');
$a2 = array('id' => 2, 'title' => 'the title');
self::assertArraysSame($a1, $a2, array('id'));
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:有没有更好或更简单的方法来完成这项任务,可能使用一些已经可用的PHP/PHPUnit函数?
编辑:请记住我并不一定要为PHPUnit的一个解决方案,如果有一个简单的PHP函数,可以做到这一点,我可以在我的测试中使用它.
我不确定这是否是比你已经使用的更好的解决方案,但是在我有这个确切需要之前我已经使用了类似的类.它能够为您提供简单的真或假响应,并且不会与测试框架相关联,这对您来说可能是也可能不是一件好事.
class RecursiveArrayCompare
{
/**
* @var array
*/
protected $ignoredKeys;
/**
*
*/
function __construct()
{
$this->ignoredKeys = array();
}
/**
* @param array $ignoredKeys
* @return RecursiveArrayCompare
*/
public function setIgnoredKeys(array $ignoredKeys)
{
$this->ignoredKeys = $ignoredKeys;
return $this;
}
/**
* @param array $a
* @param array $b
* @return bool
*/
public function compare(array $a, array $b)
{
foreach ($a as $key => $value) {
if (in_array($key, $this->ignoredKeys)) {
continue;
}
if (!array_key_exists($key, $b)) {
return false;
}
if (is_array($value) && !empty($value)) {
if (!is_array($b[$key])) {
return false;
}
if (!$this->compare($value, $b[$key])) {
return false;
}
} else {
if ($value !== $b[$key]) {
return false;
}
}
unset($b[$key]);
}
$diff = array_diff(array_keys($b), $this->ignoredKeys);
return empty($diff);
}
}
Run Code Online (Sandbox Code Playgroud)
以及基于您提供的数组的一些示例:
$arr1 = array(
'id' => 0,
'title' => 'Book1 title',
'creationDate' => '2013-01-13 17:01:07',
'pageCount' => 0
);
// only difference is value of ignored key
$arr2 = array(
'id' => 1,
'title' => 'Book1 title',
'creationDate' => '2013-01-13 17:01:07',
'pageCount' => 0
);
// has extra key
$arr3 = array(
'id' => 1,
'title' => 'Book1 title',
'creationDate' => '2013-01-13 17:01:07',
'pageCount' => 0,
'extra_key' => 1
);
// has extra key, which is ignored
$arr4 = array(
'id' => 1,
'title' => 'Book1 title',
'creationDate' => '2013-01-13 17:01:07',
'pageCount' => 0,
'ignored_key' => 1
);
// has different value
$arr5 = array(
'id' => 2,
'title' => 'Book2 title',
'creationDate' => '2013-01-13 17:01:07',
'pageCount' => 0
);
$comparer = new RecursiveArrayCompare();
$comparer->setIgnoredKeys(array('id', 'ignored_key'));
var_dump($comparer->compare($arr1, $arr2)); // true
var_dump($comparer->compare($arr1, $arr3)); // false
var_dump($comparer->compare($arr1, $arr4)); // true
var_dump($comparer->compare($arr1, $arr5)); // false
Run Code Online (Sandbox Code Playgroud)
使用诸如此类的单独类的好处是,它可以直接对此类进行单元测试,以确保其行为符合预期.如果您不能保证它们正常工作,您不希望依赖于测试工具.
| 归档时间: |
|
| 查看次数: |
1676 次 |
| 最近记录: |