Skip to content

Instantly share code, notes, and snippets.

@funder7
Last active January 15, 2022 02:21
Show Gist options
  • Save funder7/a306e78148bffdaf186da2bbc401a1cb to your computer and use it in GitHub Desktop.
Save funder7/a306e78148bffdaf186da2bbc401a1cb to your computer and use it in GitHub Desktop.
Unit testing a function that (tries to) determine if an array is associative (php >= 7.3)
<?php
namespace Tests\Unit;
// based on original work from the PHP Laravel framework
if (!function_exists('str_contains'))
{
function str_contains($haystack, $needle) {
return $needle !== '' && mb_strpos($haystack, $needle) !== false;
}
}
// Matteo Galletti - https://www.php.net/manual/en/function.array-is-list
if (!function_exists('array_is_list'))
{
function array_is_list(array $a) {
return $a === [] || (array_keys($a) === range(0, count($a) - 1));
}
}
use PHPUnit\Framework\TestCase;
/**
* @version php@>=7.3
*/
class ArrayUtilTest extends TestCase
{
/**
* Check if an array is associative
*
* @link https://gist.github.com/Thinkscape/1965669#gistcomment-4029335 (method5,6) Benchmarks
* @throws \JsonException array to json conversion problem
*/
public static function isAssociative(array $arr): bool
{
// consider empty, and [0, 1, 2, ...] sequential
if (empty($arr) || array_is_list($arr)) {
return false;
}
// first scenario:
// [ 1 => [*any*] ]
// [ 'a' => [*any*] ]
foreach ( $arr as $key => $value ) {
if (is_array($value)) {
return true;
}
}
// second scenario: read the json string
$jsonNest = json_encode($arr, JSON_THROW_ON_ERROR);
return str_contains($jsonNest, '{');
}
/**
* Associative (true) expectation
*
* @throws \JsonException
* @return void
*/
public function testAssociativeArrayCases(): void
{
foreach ( $this->associativeValues() as $associativeArray ) {
$this->assertTrue(
ArrayUtil::isAssociative($associativeArray),
">> " . json_encode($associativeArray) . "\nwas not recognized as associative"
);
}
}
/**
* Sequential (false) expectation
*
* @throws \JsonException
* @return void
*/
public function testSequentialArrayCases(): void
{
foreach ( $this->sequentialValues() as $seqArray ) {
$this->assertFalse(
ArrayUtil::isAssociative($seqArray),
'>> ' . json_encode($seqArray) . "\nwas not recognized as sequential"
);
}
}
private function associativeValues(): array
{
$assocNum[1] = 0;
$assocNum[2] = 1;
$other[0] = 'a';
$other[2] = 'b';
$other[3] = 'c';
$another = [ 'b' => 0, '1' => 1 ];
$anotherOne = [ '1' => 3, '2' => 4 ];
$assocIntCharArr[3] = [ 'a' ];
$assocIntCharAssoc[4] = [ 'a' => 'b' ];
return [
[ 'a' => 'b' ],
[ 'a' => 'a' ],
[ 'a' => [] ],
[ 'a' => 1 ],
[ 'b' => 0 ],
[ 'a' => [ 'a', 'b', 'c' ] ],
[ 'a' => 1, 'b' => 2, 'c' => [ 1, 2, 3 ] ],
[ 'a' => 1, 'b' => 2, 'c' => [ 0, 1, 2 ] ],
[ 'a' => [ 1 ] ],
[ 'b' => [ 0 ] ],
$assocNum,
$other,
$another,
$anotherOne,
$assocIntCharArr,
$assocIntCharAssoc,
];
}
private function sequentialValues(): array
{
return [
[ 1, 2, 3 ],
[ 0, 1, 2 ],
[ 0, 0, 0 ],
[ 1 ],
[ 0 ],
[ [ 10, 20, 30 ] ],
[ [ [ 30, 40, 50 ] ] ]
];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment