From fe8ab2ed619283dcbf61a9b774879d1ee6316865 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Wed, 27 Mar 2019 19:01:40 +0100 Subject: [PATCH] [PHPUnit] Add TestListenerToHooksRector --- config/level/phpunit/phpunit90.yaml | 2 + .../Class_/TestListenerToHooksRector.php | 174 ++++++++++++++++++ .../Fixture/before_list_hook.php.inc | 82 +++++++++ .../Fixture/clear_it_all.php.inc | 70 +++++++ .../TestListenerToHooksRectorTest.php | 22 +++ .../ShouldBeImplementedException.php | 2 - 6 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 config/level/phpunit/phpunit90.yaml create mode 100644 packages/PHPUnit/src/Rector/Class_/TestListenerToHooksRector.php create mode 100644 packages/PHPUnit/tests/Rector/Class_/TestListenerToHooksRector/Fixture/before_list_hook.php.inc create mode 100644 packages/PHPUnit/tests/Rector/Class_/TestListenerToHooksRector/Fixture/clear_it_all.php.inc create mode 100644 packages/PHPUnit/tests/Rector/Class_/TestListenerToHooksRector/TestListenerToHooksRectorTest.php diff --git a/config/level/phpunit/phpunit90.yaml b/config/level/phpunit/phpunit90.yaml new file mode 100644 index 000000000000..e6d4e3416cf0 --- /dev/null +++ b/config/level/phpunit/phpunit90.yaml @@ -0,0 +1,2 @@ +services: + Rector\PHPUnit\Rector\Class_\TestListenerToHooksRector: ~ diff --git a/packages/PHPUnit/src/Rector/Class_/TestListenerToHooksRector.php b/packages/PHPUnit/src/Rector/Class_/TestListenerToHooksRector.php new file mode 100644 index 000000000000..408024adeffc --- /dev/null +++ b/packages/PHPUnit/src/Rector/Class_/TestListenerToHooksRector.php @@ -0,0 +1,174 @@ + ['PHPUnit\Runner\AfterIncompleteTestHook', 'executeAfterIncompleteTest'], + 'addRiskyTest' => ['PHPUnit\Runner\AfterRiskyTestHook', 'executeAfterRiskyTest'], + 'addSkippedTest' => ['PHPUnit\Runner\AfterSkippedTestHook', 'executeAfterSkippedTest'], + 'addError' => ['PHPUnit\Runner\AfterTestErrorHook', 'executeAfterTestError'], + 'addFailure' => ['PHPUnit\Runner\AfterTestFailureHook', 'executeAfterTestFailure'], + 'addWarning' => ['PHPUnit\Runner\AfterTestWarningHook', 'executeAfterTestWarning'], + # test + 'startTest' => ['PHPUnit\Runner\BeforeTestHook', 'executeBeforeTest'], + 'endTest' => ['PHPUnit\Runner\AfterTestHook', 'executeAfterTest'], + # suite + 'startTestSuite' => ['PHPUnit\Runner\BeforeFirstTestHook', 'executeBeforeFirstTest'], + 'endTestSuite' => ['PHPUnit\Runner\AfterLastTestHook', 'executeAfterLastTest'], + ]; + + /** + * @var string + */ + private $testListenerClass; + + public function __construct(string $testListenerClass = 'PHPUnit\Framework\TestListener') + { + $this->testListenerClass = $testListenerClass; + } + + public function getDefinition(): RectorDefinition + { + return new RectorDefinition('Refactor "*TestListener.php" to particular "*Hook.php" files', [ + new CodeSample( + <<<'CODE_SAMPLE' +namespace App\Tests; + +use PHPUnit\Framework\TestListener; + +final class BeforeListHook implements TestListener +{ + public function addError(Test $test, \Throwable $t, float $time): void + { + } + + public function addWarning(Test $test, Warning $e, float $time): void + { + } + + public function addFailure(Test $test, AssertionFailedError $e, float $time): void + { + } + + public function addIncompleteTest(Test $test, \Throwable $t, float $time): void + { + } + + public function addRiskyTest(Test $test, \Throwable $t, float $time): void + { + } + + public function addSkippedTest(Test $test, \Throwable $t, float $time): void + { + } + + public function startTestSuite(TestSuite $suite): void + { + } + + public function endTestSuite(TestSuite $suite): void + { + } + + public function startTest(Test $test): void + { + echo 'start test!'; + } + + public function endTest(Test $test, float $time): void + { + echo $time; + } +} +CODE_SAMPLE + , +<<<'CODE_SAMPLE' +namespace App\Tests; + +final class BeforeListHook implements \PHPUnit\Runner\BeforeTestHook, \PHPUnit\Runner\AfterTestHook +{ + public function executeBeforeTest(Test $test): void + { + echo 'start test!'; + } + + public function executeAfterTest(Test $test, float $time): void + { + echo $time; + } +} +CODE_SAMPLE + ), + ]); + } + + /** + * List of nodes this class checks, classes that implement @see \PhpParser\Node + * @return string[] + */ + public function getNodeTypes(): array + { + return [Class_::class]; + } + + /** + * Process Node of matched type + * @param Class_ $node + */ + public function refactor(Node $node): ?Node + { + if (! $this->isType($node, $this->testListenerClass)) { + return null; + } + + foreach ($node->implements as $implement) { + if ($this->isName($implement, $this->testListenerClass)) { + $this->removeNode($implement); + } + } + + foreach ($node->getMethods() as $classMethod) { + $this->processClassMethod($node, $classMethod); + } + + return $node; + } + + private function processClassMethod(Class_ $class, ClassMethod $classMethod): void + { + foreach ($this->listenerMethodToHookInterfaces as $methodName => $hookClassAndMethod) { + /** @var string $methodName */ + if (! $this->isName($classMethod, $methodName)) { + continue; + } + + // remove empty methods + if (empty($classMethod->stmts)) { + $this->removeNode($classMethod); + } else { + $class->implements[] = new FullyQualified($hookClassAndMethod[0]); + $classMethod->name = new Identifier($hookClassAndMethod[1]); + } + } + } +} diff --git a/packages/PHPUnit/tests/Rector/Class_/TestListenerToHooksRector/Fixture/before_list_hook.php.inc b/packages/PHPUnit/tests/Rector/Class_/TestListenerToHooksRector/Fixture/before_list_hook.php.inc new file mode 100644 index 000000000000..68ef890e1582 --- /dev/null +++ b/packages/PHPUnit/tests/Rector/Class_/TestListenerToHooksRector/Fixture/before_list_hook.php.inc @@ -0,0 +1,82 @@ + +----- + diff --git a/packages/PHPUnit/tests/Rector/Class_/TestListenerToHooksRector/Fixture/clear_it_all.php.inc b/packages/PHPUnit/tests/Rector/Class_/TestListenerToHooksRector/Fixture/clear_it_all.php.inc new file mode 100644 index 000000000000..dd04e7eab0f9 --- /dev/null +++ b/packages/PHPUnit/tests/Rector/Class_/TestListenerToHooksRector/Fixture/clear_it_all.php.inc @@ -0,0 +1,70 @@ + +----- + diff --git a/packages/PHPUnit/tests/Rector/Class_/TestListenerToHooksRector/TestListenerToHooksRectorTest.php b/packages/PHPUnit/tests/Rector/Class_/TestListenerToHooksRector/TestListenerToHooksRectorTest.php new file mode 100644 index 000000000000..903d542d80ce --- /dev/null +++ b/packages/PHPUnit/tests/Rector/Class_/TestListenerToHooksRector/TestListenerToHooksRectorTest.php @@ -0,0 +1,22 @@ +doTestFiles([ + // __DIR__ . '/Fixture/clear_it_all.php.inc', + __DIR__ . '/Fixture/before_list_hook.php.inc', + ]); + } + + public function getRectorClass(): string + { + return TestListenerToHooksRector::class; + } +} diff --git a/src/Exception/ShouldBeImplementedException.php b/src/Exception/ShouldBeImplementedException.php index 4bced9b0e03c..6650920fff3c 100644 --- a/src/Exception/ShouldBeImplementedException.php +++ b/src/Exception/ShouldBeImplementedException.php @@ -6,6 +6,4 @@ final class ShouldBeImplementedException extends Exception { - } -