Skip to content

Commit f74e9be

Browse files
committed
Update AssertSameWithCountRule for assertSameSize
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.
1 parent f93aec7 commit f74e9be

File tree

3 files changed

+113
-21
lines changed

3 files changed

+113
-21
lines changed

src/Rules/PHPUnit/AssertSameWithCountRule.php

+64-19
Original file line numberDiff line numberDiff line change
@@ -37,36 +37,81 @@ public function processNode(Node $node, Scope $scope): array
3737

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

40-
if (
41-
$right instanceof Node\Expr\FuncCall
42-
&& $right->name instanceof Node\Name
43-
&& $right->name->toLowerString() === 'count'
44-
) {
45-
return [
46-
RuleErrorBuilder::message('You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, count($variable)).')
47-
->identifier('phpunit.assertCount')
48-
->build(),
49-
];
40+
$rightIsCountFuncCall = $this->isCountFuncCall($right);
41+
$rightIsCountMethodCall = $this->isCountMethodCall($right) && $this->argIsCountable($scope, $right);
42+
if (!($rightIsCountFuncCall || $rightIsCountMethodCall)) {
43+
return [];
5044
}
5145

52-
if (
53-
$right instanceof Node\Expr\MethodCall
54-
&& $right->name instanceof Node\Identifier
55-
&& $right->name->toLowerString() === 'count'
56-
&& count($right->getArgs()) === 0
57-
) {
58-
$type = $scope->getType($right->var);
46+
$left = $node->getArgs()[0]->value;
47+
$leftIsCountFuncCall = $this->isCountFuncCall($left);
48+
$leftIsCountMethodCall = $this->isCountMethodCall($left) && $this->argIsCountable($scope, $left);
49+
50+
if ($rightIsCountFuncCall) {
51+
if ($leftIsCountFuncCall) {
52+
return [
53+
RuleErrorBuilder::message('You should use assertSameSize($expected, $variable) instead of assertSame(count($expected), count($variable)).')
54+
->identifier('phpunit.assertSameSize')
55+
->build(),
56+
];
57+
} elseif ($leftIsCountMethodCall) {
58+
return [
59+
RuleErrorBuilder::message('You should use assertSameSize($expected, $variable) instead of assertSame($expected->count(), count($variable)).')
60+
->identifier('phpunit.assertSameSize')
61+
->build(),
62+
];
5963

60-
if ((new ObjectType(Countable::class))->isSuperTypeOf($type)->yes()) {
64+
} else {
65+
return [
66+
RuleErrorBuilder::message('You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, count($variable)).')
67+
->identifier('phpunit.assertCount')
68+
->build(),
69+
];
70+
}
71+
} else {
72+
if ($leftIsCountFuncCall) {
73+
return [
74+
RuleErrorBuilder::message('You should use assertSameSize($expected, $variable) instead of assertSame(count($expected), $variable->count()).')
75+
->identifier('phpunit.assertSameSize')
76+
->build(),
77+
];
78+
} elseif ($leftIsCountMethodCall) {
79+
return [
80+
RuleErrorBuilder::message('You should use assertSameSize($expected, $variable) instead of assertSame($expected->count(), $variable->count()).')
81+
->identifier('phpunit.assertSameSize')
82+
->build(),
83+
];
84+
} else {
6185
return [
6286
RuleErrorBuilder::message('You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, $variable->count()).')
6387
->identifier('phpunit.assertCount')
6488
->build(),
6589
];
6690
}
6791
}
92+
}
93+
94+
private function isCountFuncCall(Node\Expr $expr): bool
95+
{
96+
return $expr instanceof Node\Expr\FuncCall
97+
&& $expr->name instanceof Node\Name
98+
&& $expr->name->toLowerString() === 'count';
99+
}
100+
101+
private function isCountMethodCall(Node\Expr $expr): bool
102+
{
103+
return $expr instanceof Node\Expr\MethodCall
104+
&& $expr->name instanceof Node\Identifier
105+
&& $expr->name->toLowerString() === 'count'
106+
&& count($expr->getArgs()) === 0;
107+
}
108+
109+
private function argIsCountable(Scope $scope, Node\Expr $expr): bool
110+
{
111+
$type = $scope->getType($expr->var);
112+
$countableType = new ObjectType(Countable::class);
68113

69-
return [];
114+
return $countableType->isSuperTypeOf($type)->yes();
70115
}
71116

72117
}

tests/Rules/PHPUnit/AssertSameWithCountRuleTest.php

+18-2
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,29 @@ public function testRule(): void
2323
'You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, count($variable)).',
2424
10,
2525
],
26+
[
27+
'You should use assertSameSize($expected, $variable) instead of assertSame(count($expected), count($variable)).',
28+
15,
29+
],
30+
[
31+
'You should use assertSameSize($expected, $variable) instead of assertSame($expected->count(), count($variable)).',
32+
23,
33+
],
2634
[
2735
'You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, count($variable)).',
28-
22,
36+
35,
2937
],
3038
[
3139
'You should use assertCount($expectedCount, $variable) instead of assertSame($expectedCount, $variable->count()).',
32-
30,
40+
43,
41+
],
42+
[
43+
'You should use assertSameSize($expected, $variable) instead of assertSame(count($expected), $variable->count()).',
44+
51,
45+
],
46+
[
47+
'You should use assertSameSize($expected, $variable) instead of assertSame($expected->count(), $variable->count()).',
48+
61,
3349
],
3450
]);
3551
}

tests/Rules/PHPUnit/data/assert-same-count.php

+31
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,19 @@ public function testAssertSameWithCount()
1010
$this->assertSame(5, count([1, 2, 3]));
1111
}
1212

13+
public function testAssertSameWithCountExpectedWithCount()
14+
{
15+
$this->assertSame(count([10, 20]), count([1, 2, 3]));
16+
}
17+
18+
public function testAssertSameWithCountExpectedMethodWithCountMethod()
19+
{
20+
$foo = new \stdClass();
21+
$foo->bar = new Bar ();
22+
23+
$this->assertSame($foo->bar->count(), count([1, 2, 3]));
24+
}
25+
1326
public function testAssertSameWithCountMethodIsOK()
1427
{
1528
$foo = new \stdClass();
@@ -30,6 +43,24 @@ public function testAssertSameWithCountMethodForCountableVariableIsNotOK()
3043
$this->assertSame(5, $foo->bar->count());
3144
}
3245

46+
public function testAssertSameWithCountExpectedWithCountMethodForCountableVariableIsNot()
47+
{
48+
$foo = new \stdClass();
49+
$foo->bar = new Bar ();
50+
51+
$this->assertSame(count([10, 20]), $foo->bar->count());
52+
}
53+
54+
public function testAssertSameWithCountExpectedMethodWithCountMethodForCountableVariableIsNot()
55+
{
56+
$foo = new \stdClass();
57+
$foo->bar = new Bar ();
58+
$foo2 = new \stdClass();
59+
$foo2->bar = new Bar ();
60+
61+
$this->assertSame($foo2->bar->count(), $foo->bar->count());
62+
}
63+
3364
}
3465

3566
class Bar implements \Countable {

0 commit comments

Comments
 (0)