Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/set/phpunit/phpunit70.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ services:
Rector\Renaming\Rector\Annotation\RenameAnnotationRector:
PHPUnit\Framework\TestCase:
scenario: 'test'
Rector\PHPUnit\Rector\Class_\RemoveDataProviderTestPrefixRector: ~
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<?php declare(strict_types=1);

namespace Rector\PHPUnit\Rector\Class_;

use Nette\Utils\Strings;
use PhpParser\Comment\Doc;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use Rector\Rector\AbstractPHPUnitRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;

/**
* @see https://stackoverflow.com/a/46693675/1348344
*
* @see \Rector\PHPUnit\Tests\Rector\Class_\RemoveDataProviderTestPrefixRector\RemoveDataProviderTestPrefixRectorTest
*/
final class RemoveDataProviderTestPrefixRector extends AbstractPHPUnitRector
{
/**
* @var string
*/
private const DATA_PROVIDER_ANNOTATION_PATTERN = '#(@dataProvider\s+)(?<providerMethodName>test\w+)#';

/**
* @var string
*/
private const DATA_PROVIDER_EXACT_NAME_PATTERN = '#(@dataProvider\s+)(%s)#';

/**
* @var string[]
*/
private $providerMethodNamesToNewNames = [];

public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Data provider methods cannot start with "test" prefix', [
new CodeSample(
<<<'PHP'
class SomeClass extends PHPUnit\Framework\TestCase
{
/**
* @dataProvider testProvideData()
*/
public function test()
{
$nothing = 5;
}

public function testProvideData()
{
return ['123'];
}
}
PHP
,
<<<'PHP'
class SomeClass extends PHPUnit\Framework\TestCase
{
/**
* @dataProvider provideData()
*/
public function test()
{
$nothing = 5;
}

public function provideData()
{
return ['123'];
}
}
PHP
),
]);
}

/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Class_::class];
}

/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
if (! $this->isInTestClass($node)) {
return null;
}

$this->providerMethodNamesToNewNames = [];

$this->renameDataProviderAnnotationsAndCollectRenamedMethods($node);

$this->renameProviderMethods($node);

return $node;
}

private function renameDataProviderAnnotationsAndCollectRenamedMethods(Class_ $class): void
{
foreach ($class->getMethods() as $classMethod) {
if ($classMethod->getDocComment() === null) {
continue;
}

$docCommentText = $classMethod->getDocComment()->getText();
if (! Strings::match($docCommentText, self::DATA_PROVIDER_ANNOTATION_PATTERN)) {
continue;
}

// replace the name in the doc
$matches = Strings::matchAll($docCommentText, self::DATA_PROVIDER_ANNOTATION_PATTERN);
foreach ($matches as $match) {
$currentProviderMethodName = $match['providerMethodName'];

$newMethodName = Strings::substring($currentProviderMethodName, strlen('test'));
$newMethodName = lcfirst($newMethodName);

$currentMethodPattern = sprintf(self::DATA_PROVIDER_EXACT_NAME_PATTERN, $currentProviderMethodName);

$docCommentText = Strings::replace($docCommentText, $currentMethodPattern, '$1' . $newMethodName);

$this->providerMethodNamesToNewNames[$currentProviderMethodName] = $newMethodName;
}

$classMethod->setDocComment(new Doc($docCommentText));
}
}

private function renameProviderMethods(Class_ $class): void
{
foreach ($class->getMethods() as $classMethod) {
foreach ($this->providerMethodNamesToNewNames as $oldName => $newName) {
if (! $this->isName($classMethod, $oldName)) {
continue;
}

$classMethod->name = new Node\Identifier($newName);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Rector\PHPUnit\Tests\Rector\Class_\RemoveDataProviderTestPrefixRector\Fixture;

class SomeClass extends \PHPUnit\Framework\TestCase
{
/**
* @dataProvider testProvideData()
*/
public function test()
{
$nothing = 5;
}

public function testProvideData()
{
return ['123'];
}
}

?>
-----
<?php

namespace Rector\PHPUnit\Tests\Rector\Class_\RemoveDataProviderTestPrefixRector\Fixture;

class SomeClass extends \PHPUnit\Framework\TestCase
{
/**
* @dataProvider provideData()
*/
public function test()
{
$nothing = 5;
}

public function provideData()
{
return ['123'];
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

namespace Rector\PHPUnit\Tests\Rector\Class_\RemoveDataProviderTestPrefixRector\Fixture;

class MultipleDataProviders extends \PHPUnit\Framework\TestCase
{
/**
* @dataProvider testProvideData()
* @dataProvider testNextProvideData2()
* @dataProvider testNextProvideData()
*/
public function test()
{
$nothing = 5;
}

public function testProvideData()
{
return ['123'];
}

public function testNextProvideData2()
{
return ['123'];
}

public function testNextProvideData()
{
return ['123'];
}
}

?>
-----
<?php

namespace Rector\PHPUnit\Tests\Rector\Class_\RemoveDataProviderTestPrefixRector\Fixture;

class MultipleDataProviders extends \PHPUnit\Framework\TestCase
{
/**
* @dataProvider provideData()
* @dataProvider nextProvideData2()
* @dataProvider nextProvideData()
*/
public function test()
{
$nothing = 5;
}

public function provideData()
{
return ['123'];
}

public function nextProvideData2()
{
return ['123'];
}

public function nextProvideData()
{
return ['123'];
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace Rector\PHPUnit\Tests\Rector\Class_\RemoveDataProviderTestPrefixRector\Fixture;

class WithTestAnnotation extends \PHPUnit\Framework\TestCase
{
/**
* @test
* @dataProvider testProvideDataForWithATestAnnotation()
*/
public function test()
{
$nothing = 5;
}

public function testProvideDataForWithATestAnnotation()
{
return ['123'];
}
}

?>
-----
<?php

namespace Rector\PHPUnit\Tests\Rector\Class_\RemoveDataProviderTestPrefixRector\Fixture;

class WithTestAnnotation extends \PHPUnit\Framework\TestCase
{
/**
* @test
* @dataProvider provideDataForWithATestAnnotation()
*/
public function test()
{
$nothing = 5;
}

public function provideDataForWithATestAnnotation()
{
return ['123'];
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php declare(strict_types=1);

namespace Rector\PHPUnit\Tests\Rector\Class_\RemoveDataProviderTestPrefixRector;

use Iterator;
use Rector\PHPUnit\Rector\Class_\RemoveDataProviderTestPrefixRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class RemoveDataProviderTestPrefixRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideDataForTest()
*/
public function test(string $file): void
{
$this->doTestFile($file);
}

public function provideDataForTest(): Iterator
{
yield [__DIR__ . '/Fixture/fixture.php.inc'];
yield [__DIR__ . '/Fixture/with_test_annotation.php.inc'];
yield [__DIR__ . '/Fixture/multiple_data_providers.php.inc'];
}

protected function getRectorClass(): string
{
return RemoveDataProviderTestPrefixRector::class;
}
}