Merge pull request #3021 from nightlinus/phpunit9-assertContainsEquals

add phpunit 9 rector to convert non-strict assertContains
This commit is contained in:
Tomas Votruba 2020-03-15 19:17:01 +01:00 committed by GitHub
commit a2a32a4919
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 254 additions and 1 deletions

View File

@ -1,3 +1,4 @@
services:
Rector\PHPUnit\Rector\Class_\TestListenerToHooksRector: null
Rector\PHPUnit\Rector\MethodCall\ExplicitPhpErrorApiRector: null
Rector\PHPUnit\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector: null

View File

@ -1,4 +1,4 @@
# All 464 Rectors Overview
# All 465 Rectors Overview
- [Projects](#projects)
- [General](#general)
@ -5677,6 +5677,32 @@ Change assertContains()/assertNotContains() method to new string and iterable al
<br>
### `SpecificAssertContainsWithoutIdentityRector`
- class: [`Rector\PHPUnit\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector`](/../master/rules/phpunit/src/Rector/MethodCall/SpecificAssertContainsWithoutIdentityRector.php)
- [test fixtures](/../master/rules/phpunit/tests/Rector/MethodCall/SpecificAssertContainsWithoutIdentityRector/Fixture)
Change assertContains()/assertNotContains() with non-strict comparison to new specific alternatives
```diff
<?php
-final class SomeTest extends \PHPUnit\Framework\TestCase
+final class SomeTest extends TestCase
{
public function test()
{
$objects = [ new \stdClass(), new \stdClass(), new \stdClass() ];
- $this->assertContains(new \stdClass(), $objects, 'message', false, false);
- $this->assertNotContains(new \stdClass(), $objects, 'message', false, false);
+ $this->assertContainsEquals(new \stdClass(), $objects, 'message');
+ $this->assertNotContainsEquals(new \stdClass(), $objects, 'message');
}
}
```
<br>
### `SpecificAssertInternalTypeRector`
- class: [`Rector\PHPUnit\Rector\MethodCall\SpecificAssertInternalTypeRector`](/../master/rules/phpunit/src/Rector/MethodCall/SpecificAssertInternalTypeRector.php)

View File

@ -0,0 +1,110 @@
<?php
declare(strict_types=1);
namespace Rector\PHPUnit\Rector\MethodCall;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Identifier;
use PHPStan\Type\StringType;
use Rector\Core\Rector\AbstractPHPUnitRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
/**
* @see https://github.com/sebastianbergmann/phpunit/issues/3426
* @see \Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector\SpecificAssertContainsWithoutIdentityRectorTest
*/
final class SpecificAssertContainsWithoutIdentityRector extends AbstractPHPUnitRector
{
/**
* @var string[][]
*/
private const OLD_METHODS_NAMES_TO_NEW_NAMES = [
'string' => [
'assertContains' => 'assertContainsEquals',
'assertNotContains' => 'assertNotContainsEquals',
],
];
public function getDefinition(): RectorDefinition
{
return new RectorDefinition(
'Change assertContains()/assertNotContains() with non-strict comparison to new specific alternatives',
[
new CodeSample(
<<<'PHP'
<?php
final class SomeTest extends \PHPUnit\Framework\TestCase
{
public function test()
{
$objects = [ new \stdClass(), new \stdClass(), new \stdClass() ];
$this->assertContains(new \stdClass(), $objects, 'message', false, false);
$this->assertNotContains(new \stdClass(), $objects, 'message', false, false);
}
}
PHP
,
<<<'PHP'
<?php
final class SomeTest extends TestCase
{
public function test()
{
$objects = [ new \stdClass(), new \stdClass(), new \stdClass() ];
$this->assertContainsEquals(new \stdClass(), $objects, 'message');
$this->assertNotContainsEquals(new \stdClass(), $objects, 'message');
}
}
PHP
),
]
);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [MethodCall::class, StaticCall::class];
}
/**
* @param MethodCall|StaticCall $node
*/
public function refactor(Node $node): ?Node
{
if (! $this->isPHPUnitMethodNames($node, ['assertContains', 'assertNotContains'])) {
return null;
}
//when second argument is string: do nothing
if ($this->isStaticType($node->args[1]->value, StringType::class)) {
return null;
}
//when less then 5 arguments given: do nothing
if (! isset($node->args[4]) || $node->args[4]->value === null) {
return null;
}
//when 5th argument check identity is true: do nothing
if ($this->isValue($node->args[4]->value, true)) {
return null;
}
/* here we search for element of array without identity check and we can replace functions */
$methodName = $this->getName($node->name);
$node->name = new Identifier(self::OLD_METHODS_NAMES_TO_NEW_NAMES['string'][$methodName]);
unset($node->args[3], $node->args[4]);
return $node;
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector\Fixture;
use PHPUnit\Framework\TestCase;
use stdClass;
final class CheckIdentity extends TestCase
{
public function test()
{
$objects = [ new stdClass(), new stdClass(), new stdClass() ];
$this->assertContains(new stdClass(), $objects, 'message', false, true);
$this->assertNotContains(new stdClass(), $objects, 'message', false, true);
}
}
?>

View File

@ -0,0 +1,37 @@
<?php
namespace Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector\Fixture;
use PHPUnit\Framework\TestCase;
use stdClass;
final class SomeTest extends TestCase
{
public function test()
{
$objects = [ new stdClass(), new stdClass(), new stdClass() ];
$this->assertContains(new stdClass(), $objects, 'message', false, false);
$this->assertNotContains(new stdClass(), $objects, 'message', false, false);
}
}
?>
-----
<?php
namespace Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector\Fixture;
use PHPUnit\Framework\TestCase;
use stdClass;
final class SomeTest extends TestCase
{
public function test()
{
$objects = [ new stdClass(), new stdClass(), new stdClass() ];
$this->assertContainsEquals(new stdClass(), $objects, 'message');
$this->assertNotContainsEquals(new stdClass(), $objects, 'message');
}
}
?>

View File

@ -0,0 +1,16 @@
<?php
namespace Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector\Fixture;
use PHPUnit\Framework\TestCase;
use stdClass;
final class PartialArguments extends TestCase
{
public function test()
{
$objects = [ new stdClass(), new stdClass(), new stdClass() ];
$this->assertContains(new stdClass(), $objects, 'message', false);
$this->assertNotContains(new stdClass(), $objects, 'message', false);
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector\Fixture;
use PHPUnit\Framework\TestCase;
final class NoChangeOnStrings extends TestCase
{
public function test()
{
$this->assertContains('foo', 'foo bar', 'message', false, false);
$this->assertNotContains('foo', 'foo bar', 'message', false, false);
}
}

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Rector\PHPUnit\Tests\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector;
use Iterator;
use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase;
use Rector\PHPUnit\Rector\MethodCall\SpecificAssertContainsWithoutIdentityRector;
final class SpecificAssertContainsWithoutIdentityRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(string $file): void
{
$this->doTestFile($file);
}
public function provideData(): Iterator
{
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
protected function getRectorClass(): string
{
return SpecificAssertContainsWithoutIdentityRector::class;
}
}