Skip to content

Commit 2db2e4c

Browse files
authored
[PHPUnit60] Remove addToAssertionCount() calls in AddDoesNotPerformAssertionToNonAssertingTestRector (#763)
1 parent 6ad762b commit 2db2e4c

4 files changed

Lines changed: 173 additions & 0 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\PHPUnit60\Rector\ClassMethod\AddDoesNotPerformAssertionToNonAssertingTestRector\Fixture;
4+
5+
class RemoveAddToAssertionCount extends \PHPUnit\Framework\TestCase
6+
{
7+
public function test()
8+
{
9+
$this->someMethodCall();
10+
$this->addToAssertionCount(1);
11+
}
12+
13+
private function someMethodCall()
14+
{
15+
}
16+
}
17+
18+
?>
19+
-----
20+
<?php
21+
22+
namespace Rector\PHPUnit\Tests\PHPUnit60\Rector\ClassMethod\AddDoesNotPerformAssertionToNonAssertingTestRector\Fixture;
23+
24+
class RemoveAddToAssertionCount extends \PHPUnit\Framework\TestCase
25+
{
26+
/**
27+
* @doesNotPerformAssertions
28+
*/
29+
public function test()
30+
{
31+
$this->someMethodCall();
32+
}
33+
34+
private function someMethodCall()
35+
{
36+
}
37+
}
38+
39+
?>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\PHPUnit60\Rector\ClassMethod\AddDoesNotPerformAssertionToNonAssertingTestRector\Fixture;
4+
5+
class RemoveAddToAssertionCountInTryCatch extends \PHPUnit\Framework\TestCase
6+
{
7+
public function test()
8+
{
9+
try {
10+
$this->someMethodCall();
11+
$this->addToAssertionCount(1);
12+
} catch (\Throwable $throwable) {
13+
}
14+
}
15+
16+
private function someMethodCall()
17+
{
18+
}
19+
}
20+
21+
?>
22+
-----
23+
<?php
24+
25+
namespace Rector\PHPUnit\Tests\PHPUnit60\Rector\ClassMethod\AddDoesNotPerformAssertionToNonAssertingTestRector\Fixture;
26+
27+
class RemoveAddToAssertionCountInTryCatch extends \PHPUnit\Framework\TestCase
28+
{
29+
/**
30+
* @doesNotPerformAssertions
31+
*/
32+
public function test()
33+
{
34+
try {
35+
$this->someMethodCall();
36+
} catch (\Throwable $throwable) {
37+
}
38+
}
39+
40+
private function someMethodCall()
41+
{
42+
}
43+
}
44+
45+
?>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Rector\PHPUnit\Tests\PHPUnit60\Rector\ClassMethod\AddDoesNotPerformAssertionToNonAssertingTestRector\Fixture;
4+
5+
class RemoveAddToAssertionCountWithComment extends \PHPUnit\Framework\TestCase
6+
{
7+
public function test()
8+
{
9+
$this->someMethodCall();
10+
11+
$this->addToAssertionCount(1); // Verify that no exception is thrown
12+
}
13+
14+
private function someMethodCall()
15+
{
16+
}
17+
}
18+
19+
?>
20+
-----
21+
<?php
22+
23+
namespace Rector\PHPUnit\Tests\PHPUnit60\Rector\ClassMethod\AddDoesNotPerformAssertionToNonAssertingTestRector\Fixture;
24+
25+
class RemoveAddToAssertionCountWithComment extends \PHPUnit\Framework\TestCase
26+
{
27+
/**
28+
* @doesNotPerformAssertions
29+
*/
30+
public function test()
31+
{
32+
$this->someMethodCall();
33+
}
34+
35+
private function someMethodCall()
36+
{
37+
}
38+
}
39+
40+
?>

‎rules/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector.php‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55
namespace Rector\PHPUnit\PHPUnit60\Rector\ClassMethod;
66

77
use PhpParser\Node;
8+
use PhpParser\Node\Expr\MethodCall;
89
use PhpParser\Node\Stmt\ClassMethod;
10+
use PhpParser\Node\Stmt\Expression;
11+
use PhpParser\Node\Stmt\Nop;
12+
use PhpParser\NodeVisitor;
913
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
1014
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
1115
use PHPStan\Reflection\ClassReflection;
@@ -104,6 +108,8 @@ public function refactor(Node $node): ?Node
104108
return null;
105109
}
106110

111+
$this->removeAddToAssertionCountCalls($node);
112+
107113
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
108114
$phpDocInfo->addPhpDocTagNode(new PhpDocTagNode('@doesNotPerformAssertions', new GenericTagValueNode('')));
109115

@@ -143,6 +149,49 @@ private function shouldSkipClassMethod(ClassMethod $classMethod): bool
143149
return $this->mockedVariableAnalyzer->containsMockAsUsedVariable($classMethod);
144150
}
145151

152+
/**
153+
* The assertion count fakes an assertion, but the "@doesNotPerformAssertions" annotation makes it obsolete
154+
*/
155+
private function removeAddToAssertionCountCalls(ClassMethod $classMethod): void
156+
{
157+
$hasJustRemovedCall = false;
158+
159+
$this->traverseNodesWithCallable($classMethod, function (Node $node) use (&$hasJustRemovedCall): ?int {
160+
// a comment on the same line as the removed call is parsed as a nop statement right behind it
161+
if ($hasJustRemovedCall && $node instanceof Nop) {
162+
return NodeVisitor::REMOVE_NODE;
163+
}
164+
165+
$hasJustRemovedCall = false;
166+
167+
if (! $this->isAddToAssertionCountExpression($node)) {
168+
return null;
169+
}
170+
171+
$hasJustRemovedCall = true;
172+
173+
return NodeVisitor::REMOVE_NODE;
174+
});
175+
}
176+
177+
private function isAddToAssertionCountExpression(Node $node): bool
178+
{
179+
if (! $node instanceof Expression) {
180+
return false;
181+
}
182+
183+
if (! $node->expr instanceof MethodCall) {
184+
return false;
185+
}
186+
187+
$methodCall = $node->expr;
188+
if (! $this->isName($methodCall->var, 'this')) {
189+
return false;
190+
}
191+
192+
return $this->isName($methodCall->name, 'addToAssertionCount');
193+
}
194+
146195
private function isInTwigIntegrationTestCase(ClassMethod $classMethod): bool
147196
{
148197
$classReflection = $this->reflectionResolver->resolveClassReflection($classMethod);

0 commit comments

Comments
 (0)