Skip to content

Commit

Permalink
Update AssertSameWithCountRule for assertSameSize
Browse files Browse the repository at this point in the history
Expanded the AssertSameWithCountRule in PHPUnit rules to handle additional scenarios. Now the rule checks if both sides of the assertSame are counts, and suggests assertSameSize instead when necessary. The modification enhances the rule's applicability and accuracy.
  • Loading branch information
o0h committed Apr 4, 2024
1 parent f93aec7 commit f74e9be
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 21 deletions.
83 changes: 64 additions & 19 deletions src/Rules/PHPUnit/AssertSameWithCountRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,36 +37,81 @@ public function processNode(Node $node, Scope $scope): array

$right = $node->getArgs()[1]->value;

if (
$right instanceof Node\Expr\FuncCall
&& $right->name instanceof Node\Name
&& $right->name->toLowerString() === 'count'
) {
return [
RuleErrorBuilder::message('You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, count($variable)).')
->identifier('phpunit.assertCount')
->build(),
];
$rightIsCountFuncCall = $this->isCountFuncCall($right);
$rightIsCountMethodCall = $this->isCountMethodCall($right) && $this->argIsCountable($scope, $right);
if (!($rightIsCountFuncCall || $rightIsCountMethodCall)) {
return [];
}

if (
$right instanceof Node\Expr\MethodCall
&& $right->name instanceof Node\Identifier
&& $right->name->toLowerString() === 'count'
&& count($right->getArgs()) === 0
) {
$type = $scope->getType($right->var);
$left = $node->getArgs()[0]->value;
$leftIsCountFuncCall = $this->isCountFuncCall($left);
$leftIsCountMethodCall = $this->isCountMethodCall($left) && $this->argIsCountable($scope, $left);

if ($rightIsCountFuncCall) {
if ($leftIsCountFuncCall) {
return [
RuleErrorBuilder::message('You should use assertSameSize($expected, $variable) instead of assertSame(count($expected), count($variable)).')
->identifier('phpunit.assertSameSize')
->build(),
];
} elseif ($leftIsCountMethodCall) {
return [
RuleErrorBuilder::message('You should use assertSameSize($expected, $variable) instead of assertSame($expected->count(), count($variable)).')
->identifier('phpunit.assertSameSize')
->build(),
];

if ((new ObjectType(Countable::class))->isSuperTypeOf($type)->yes()) {
} else {
return [
RuleErrorBuilder::message('You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, count($variable)).')
->identifier('phpunit.assertCount')
->build(),
];
}
} else {
if ($leftIsCountFuncCall) {
return [
RuleErrorBuilder::message('You should use assertSameSize($expected, $variable) instead of assertSame(count($expected), $variable->count()).')
->identifier('phpunit.assertSameSize')
->build(),
];
} elseif ($leftIsCountMethodCall) {
return [
RuleErrorBuilder::message('You should use assertSameSize($expected, $variable) instead of assertSame($expected->count(), $variable->count()).')
->identifier('phpunit.assertSameSize')
->build(),
];
} else {
return [
RuleErrorBuilder::message('You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, $variable->count()).')
->identifier('phpunit.assertCount')
->build(),
];
}
}
}

private function isCountFuncCall(Node\Expr $expr): bool
{
return $expr instanceof Node\Expr\FuncCall
&& $expr->name instanceof Node\Name
&& $expr->name->toLowerString() === 'count';
}

private function isCountMethodCall(Node\Expr $expr): bool
{
return $expr instanceof Node\Expr\MethodCall
&& $expr->name instanceof Node\Identifier
&& $expr->name->toLowerString() === 'count'
&& count($expr->getArgs()) === 0;
}

private function argIsCountable(Scope $scope, Node\Expr $expr): bool
{
$type = $scope->getType($expr->var);

Check failure on line 111 in src/Rules/PHPUnit/AssertSameWithCountRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.2, lowest)

Access to an undefined property PhpParser\Node\Expr::$var.

Check failure on line 111 in src/Rules/PHPUnit/AssertSameWithCountRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.2, highest)

Access to an undefined property PhpParser\Node\Expr::$var.

Check failure on line 111 in src/Rules/PHPUnit/AssertSameWithCountRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.3, lowest)

Access to an undefined property PhpParser\Node\Expr::$var.

Check failure on line 111 in src/Rules/PHPUnit/AssertSameWithCountRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.3, highest)

Access to an undefined property PhpParser\Node\Expr::$var.

Check failure on line 111 in src/Rules/PHPUnit/AssertSameWithCountRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.4, lowest)

Access to an undefined property PhpParser\Node\Expr::$var.

Check failure on line 111 in src/Rules/PHPUnit/AssertSameWithCountRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.4, highest)

Access to an undefined property PhpParser\Node\Expr::$var.

Check failure on line 111 in src/Rules/PHPUnit/AssertSameWithCountRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, lowest)

Access to an undefined property PhpParser\Node\Expr::$var.

Check failure on line 111 in src/Rules/PHPUnit/AssertSameWithCountRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, highest)

Access to an undefined property PhpParser\Node\Expr::$var.

Check failure on line 111 in src/Rules/PHPUnit/AssertSameWithCountRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, lowest)

Access to an undefined property PhpParser\Node\Expr::$var.

Check failure on line 111 in src/Rules/PHPUnit/AssertSameWithCountRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, highest)

Access to an undefined property PhpParser\Node\Expr::$var.

Check failure on line 111 in src/Rules/PHPUnit/AssertSameWithCountRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, lowest)

Access to an undefined property PhpParser\Node\Expr::$var.

Check failure on line 111 in src/Rules/PHPUnit/AssertSameWithCountRule.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, highest)

Access to an undefined property PhpParser\Node\Expr::$var.
$countableType = new ObjectType(Countable::class);

return [];
return $countableType->isSuperTypeOf($type)->yes();
}

}
20 changes: 18 additions & 2 deletions tests/Rules/PHPUnit/AssertSameWithCountRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,29 @@ public function testRule(): void
'You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, count($variable)).',
10,
],
[
'You should use assertSameSize($expected, $variable) instead of assertSame(count($expected), count($variable)).',
15,
],
[
'You should use assertSameSize($expected, $variable) instead of assertSame($expected->count(), count($variable)).',
23,
],
[
'You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, count($variable)).',
22,
35,
],
[
'You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, $variable->count()).',
30,
43,
],
[
'You should use assertSameSize($expected, $variable) instead of assertSame(count($expected), $variable->count()).',
51,
],
[
'You should use assertSameSize($expected, $variable) instead of assertSame($expected->count(), $variable->count()).',
61,
],
]);
}
Expand Down
31 changes: 31 additions & 0 deletions tests/Rules/PHPUnit/data/assert-same-count.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ public function testAssertSameWithCount()
$this->assertSame(5, count([1, 2, 3]));
}

public function testAssertSameWithCountExpectedWithCount()
{
$this->assertSame(count([10, 20]), count([1, 2, 3]));
}

public function testAssertSameWithCountExpectedMethodWithCountMethod()
{
$foo = new \stdClass();
$foo->bar = new Bar ();

$this->assertSame($foo->bar->count(), count([1, 2, 3]));
}

public function testAssertSameWithCountMethodIsOK()
{
$foo = new \stdClass();
Expand All @@ -30,6 +43,24 @@ public function testAssertSameWithCountMethodForCountableVariableIsNotOK()
$this->assertSame(5, $foo->bar->count());
}

public function testAssertSameWithCountExpectedWithCountMethodForCountableVariableIsNot()
{
$foo = new \stdClass();
$foo->bar = new Bar ();

$this->assertSame(count([10, 20]), $foo->bar->count());
}

public function testAssertSameWithCountExpectedMethodWithCountMethodForCountableVariableIsNot()
{
$foo = new \stdClass();
$foo->bar = new Bar ();
$foo2 = new \stdClass();
$foo2->bar = new Bar ();

$this->assertSame($foo2->bar->count(), $foo->bar->count());
}

}

class Bar implements \Countable {
Expand Down

0 comments on commit f74e9be

Please sign in to comment.