Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added assertArrayIsList() #4818

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions ChangeLog-10.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ All notable changes of the PHPUnit 10.0 release series are documented in this fi
* [#4657](https://github.com/sebastianbergmann/phpunit/pull/4657): Add `--exclude-testsuite` option
* [#4709](https://github.com/sebastianbergmann/phpunit/issues/4709): Support `never` type in test double code generator
* [#4737](https://github.com/sebastianbergmann/phpunit/issues/4737): Support intersection types in test double code generator
* [#4818](https://github.com/sebastianbergmann/phpunit/pull/4818): Add `assertArrayIsList`
* `@excludeGlobalVariableFromBackup variable` annotation for excluding a global variable from the backup/restore of global and super-global variables
* `#[ExcludeGlobalVariableFromBackup('variable')]` attribute for excluding a global variable from the backup/restore of global and super-global variables
* `@excludeStaticPropertyFromBackup className propertyName` annotation for excluding a static property from the backup/restore of static properties in user-defined classes
Expand Down
15 changes: 15 additions & 0 deletions src/Framework/Assert.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use Generator;
use PHPUnit\Event;
use PHPUnit\Framework\Constraint\ArrayHasKey;
use PHPUnit\Framework\Constraint\ArrayIsList;
use PHPUnit\Framework\Constraint\Callback;
use PHPUnit\Framework\Constraint\ClassHasAttribute;
use PHPUnit\Framework\Constraint\ClassHasStaticAttribute;
Expand Down Expand Up @@ -113,6 +114,15 @@ public static function assertArrayNotHasKey(int|string $key, array|ArrayAccess $
static::assertThat($array, $constraint, $message);
}

public static function assertArrayIsList(array $array, string $message = ''): void
{
static::assertThat(
$array,
new ArrayIsList,
$message
);
}

/**
* Asserts that a haystack contains a needle.
*
Expand Down Expand Up @@ -2170,6 +2180,11 @@ public static function arrayHasKey(int|string $key): ArrayHasKey
return new ArrayHasKey($key);
}

public static function arrayIsList(): ArrayIsList
{
return new ArrayIsList;
}

public static function equalTo(mixed $value): IsEqual
{
return new IsEqual($value, 0.0, false, false);
Expand Down
26 changes: 26 additions & 0 deletions src/Framework/Assert/Functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
namespace PHPUnit\Framework;

use function func_get_args;
use function function_exists;
use ArrayAccess;
use Countable;
use PHPUnit\Framework\Constraint\ArrayHasKey;
use PHPUnit\Framework\Constraint\ArrayIsList;
use PHPUnit\Framework\Constraint\Callback;
use PHPUnit\Framework\Constraint\ClassHasAttribute;
use PHPUnit\Framework\Constraint\ClassHasStaticAttribute;
Expand Down Expand Up @@ -103,6 +105,23 @@ function assertArrayNotHasKey(int|string $key, array|ArrayAccess $array, string
}
}

if (!function_exists('PHPUnit\Framework\assertArrayIsList')) {
/**
* Asserts that an array is list.
*
* @throws Exception
* @throws ExpectationFailedException
*
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*
* @see Assert::assertArrayIsList()
*/
function assertArrayIsList(array $array, string $message = ''): void
{
Assert::assertArrayIsList(...func_get_args());
}
}

if (!function_exists('PHPUnit\Framework\assertContains')) {
/**
* Asserts that a haystack contains a needle.
Expand Down Expand Up @@ -2383,6 +2402,13 @@ function arrayHasKey(int|string $key): ArrayHasKey
}
}

if (!function_exists('PHPUnit\Framework\arrayIsList')) {
function arrayIsList(): ArrayIsList
{
return Assert::arrayIsList();
}
}

if (!function_exists('PHPUnit\Framework\equalTo')) {
function equalTo(mixed $value): IsEqual
{
Expand Down
64 changes: 64 additions & 0 deletions src/Framework/Constraint/Traversable/ArrayIsList.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Framework\Constraint;

use function is_array;

/**
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
*/
final class ArrayIsList extends Constraint
{
/**
* Returns a string representation of the constraint.
*/
public function toString(): string
{
return 'is list';
}

/**
* Evaluates the constraint for parameter $other. Returns true if the
* constraint is met, false otherwise.
*/
protected function matches(mixed $other): bool
{
if (!is_array($other)) {
return false;
}

if ($other === []) {
return true;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (function_exists('array_is_list')) {
return array_is_list($other);
}

On PHP 8.1, we have a native function for that. I suggest we leverage it if it's available.

$expectedKey = 0;

foreach ($other as $key => $value) {
if ($key !== $expectedKey) {
return false;
}

$expectedKey++;
}

return true;
}

/**
* Returns the description of the failure.
*
* The beginning of failure messages is "Failed asserting that" in most
* cases. This method should return the second part of that sentence.
*/
protected function failureDescription(mixed $other): string
{
return 'an array ' . $this->toString();
}
}
26 changes: 26 additions & 0 deletions tests/unit/Framework/AssertTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,27 @@ public function testAssertArrayNotHasKeyPropertlyFailsWithArrayAccessValue(): vo
$this->assertArrayNotHasKey('bar', $array);
}

public function testAssertArrayIsList(): void
{
$this->assertArrayIsList([0, 1, 2]);

$this->expectException(AssertionFailedError::class);

$this->assertArrayIsList([0 => 0, 2 => 2, 3 => 3]);
}

public function testAssertArrayIsListWithEmptyArray(): void
{
$this->assertArrayIsList([]);
}

public function testAssertArrayIsListFailsWithStringKeys(): void
{
$this->expectException(AssertionFailedError::class);

$this->assertArrayIsList(['string' => 0]);
}

public function testAssertArrayContainsOnlyIntegers(): void
{
$this->assertContainsOnly('integer', [1, 2, 3]);
Expand Down Expand Up @@ -946,6 +967,11 @@ public function testAssertThatArrayHasKey(): void
$this->assertThat(['foo' => 'bar'], $this->arrayHasKey('foo'));
}

public function testAssertThatArrayIsList(): void
{
$this->assertThat([0, 1, 2], $this->arrayIsList());
}

public function testAssertThatEqualTo(): void
{
$this->assertThat('foo', $this->equalTo('foo'));
Expand Down
119 changes: 119 additions & 0 deletions tests/unit/Framework/Constraint/ArrayIsListTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Framework\Constraint;

use PHPUnit\Framework\ExpectationFailedException;
use PHPUnit\Framework\TestFailure;

/**
* @small
*/
final class ArrayIsListTest extends ConstraintTestCase
{
public function testConstraintArrayIsListWhenEmpty(): void
{
$constraint = new ArrayIsList();

$this->assertTrue($constraint->evaluate([], '', true));
}

public function testConstraintArrayIsNotList(): void
{
$constraint = new ArrayIsList();

$this->assertFalse($constraint->evaluate([1 => 1], '', true));
$this->assertEquals('is list', $constraint->toString());
$this->assertCount(1, $constraint);

try {
$constraint->evaluate([1 => 1]);
} catch (ExpectationFailedException $e) {
$this->assertEquals(
<<<'EOF'
Failed asserting that an array is list.
EOF
,
TestFailure::exceptionToString($e)
);

return;
}

$this->fail();
}

public function testConstraintArrayIsNotListWithFilteredArray(): void
{
$constraint = new ArrayIsList();

$this->assertFalse($constraint->evaluate([0 => 0, 1 => 1, 3 => 3], '', true));
$this->assertEquals('is list', $constraint->toString());
$this->assertCount(1, $constraint);

try {
$constraint->evaluate([1 => 1]);
} catch (ExpectationFailedException $e) {
$this->assertEquals(
<<<'EOF'
Failed asserting that an array is list.
EOF
,
TestFailure::exceptionToString($e)
);

return;
}

$this->fail();
}

public function testConstraintArrayIsNotListWithCustomMessage(): void
{
$constraint = new ArrayIsList();

try {
$constraint->evaluate([1 => 1], 'custom message');
} catch (ExpectationFailedException $e) {
$this->assertEquals(
<<<'EOF'
custom message
Failed asserting that an array is list.
EOF
,
TestFailure::exceptionToString($e)
);

return;
}

$this->fail();
}

public function testConstraintArrayIsNotListWhenNotArray(): void
{
$constraint = new ArrayIsList();

try {
$constraint->evaluate('not array');
} catch (ExpectationFailedException $e) {
$this->assertEquals(
<<<'EOF'
Failed asserting that an array is list.
EOF
,
TestFailure::exceptionToString($e)
);
}
}
}
25 changes: 25 additions & 0 deletions tests/unit/Framework/ConstraintTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,31 @@ public function testConstraintArrayNotHasKey2(): void
custom message
Failed asserting that an array does not have the key 0.
EOF
,
TestFailure::exceptionToString($e)
);

return;
}

$this->fail();
}

public function testConstraintArrayIsNotList(): void
{
$constraint = Assert::logicalNot(
Assert::arrayIsList()
);

try {
$constraint->evaluate([0, 1, 2], 'custom message');
} catch (ExpectationFailedException $e) {
$this->assertEquals(
<<<'EOF'
custom message
Failed asserting that an array is not list.
EOF
,
TestFailure::exceptionToString($e)
Expand Down