diff --git a/.github/workflows/code_analysis.yaml b/.github/workflows/code_analysis.yaml index abf35b6d..5a7c5c1e 100644 --- a/.github/workflows/code_analysis.yaml +++ b/.github/workflows/code_analysis.yaml @@ -40,6 +40,10 @@ jobs: name: 'Bench' run: php bench/does_not_perform_assertion_lifecycle_bench.php + - + name: 'Bench abstract classes' + run: php bench/does_not_perform_assertion_abstract_class_bench.php + name: ${{ matrix.actions.name }} runs-on: ubuntu-latest timeout-minutes: 10 diff --git a/bench/does_not_perform_assertion_abstract_class_bench.php b/bench/does_not_perform_assertion_abstract_class_bench.php new file mode 100644 index 00000000..364392c4 --- /dev/null +++ b/bench/does_not_perform_assertion_abstract_class_bench.php @@ -0,0 +1,106 @@ +create(); +$rectorConfig->boot(); + +/** @var TestingParser $testingParser */ +$testingParser = $rectorConfig->make(TestingParser::class); + +/** @var BetterNodeFinder $betterNodeFinder */ +$betterNodeFinder = $rectorConfig->make(BetterNodeFinder::class); + +$rector = $rectorConfig->make(AddDoesNotPerformAssertionToNonAssertingTestRector::class); + +$classMethods = []; +foreach ($testFilePaths as $testFilePath) { + $stmts = $testingParser->parseFileToDecoratedNodes($testFilePath); + $classMethods = [...$classMethods, ...$betterNodeFinder->findInstanceOf($stmts, ClassMethod::class)]; +} + +$cpuSeconds = static function (): float { + $usage = getrusage(); + return $usage['ru_utime.tv_sec'] + $usage['ru_utime.tv_usec'] / 1_000_000 + + $usage['ru_stime.tv_sec'] + $usage['ru_stime.tv_usec'] / 1_000_000; +}; + +$wallStart = microtime(true); +$cpuStart = $cpuSeconds(); + +$changedCount = 0; +foreach ($classMethods as $classMethod) { + if ($rector->refactor($classMethod) instanceof ClassMethod) { + ++$changedCount; + } +} + +$cpu = $cpuSeconds() - $cpuStart; +$wall = microtime(true) - $wallStart; + +array_map('unlink', glob($directory . '/*.php')); +@rmdir($directory); + +printf('test classes: %d, test methods: %d, changed: %d%s', count($testFilePaths), count($classMethods), $changedCount, PHP_EOL); +printf('CPU: %.4f s (%.3f ms/method)%s', $cpu, $cpu / count($classMethods) * 1000, PHP_EOL); +printf('wall: %.4f s%s', $wall, PHP_EOL); + +if ($cpu > MAX_CPU_SECONDS) { + printf('CPU %.4f s is over the %.1f s limit%s', $cpu, MAX_CPU_SECONDS, PHP_EOL); + exit(1); +} diff --git a/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/skip_abstract_class_inherited_test_with_asserting_child.php.inc b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/skip_abstract_class_inherited_test_with_asserting_child.php.inc new file mode 100644 index 00000000..3a993b19 --- /dev/null +++ b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/skip_abstract_class_inherited_test_with_asserting_child.php.inc @@ -0,0 +1,21 @@ +assertTrue(true); + } +} diff --git a/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/skip_abstract_class_test_method.php.inc b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/skip_abstract_class_test_method.php.inc new file mode 100644 index 00000000..a3b05170 --- /dev/null +++ b/rules-tests/PHPUnit60/Rector/ClassMethod/AddDoesNotPerformAssertionToNonAssertingTestRector/Fixture/skip_abstract_class_test_method.php.inc @@ -0,0 +1,14 @@ +isInAbstractClass($classMethod)) { + return true; + } + // the parent test case asserts in its own integration methods if ($this->isInTwigIntegrationTestCase($classMethod)) { return true; @@ -220,6 +225,16 @@ private function isInTrait(ClassMethod $classMethod): bool return $classReflection->isTrait(); } + private function isInAbstractClass(ClassMethod $classMethod): bool + { + $classReflection = $this->reflectionResolver->resolveClassReflection($classMethod); + if (! $classReflection instanceof ClassReflection) { + return false; + } + + return $classReflection->isAbstract(); + } + private function isInTwigIntegrationTestCase(ClassMethod $classMethod): bool { $classReflection = $this->reflectionResolver->resolveClassReflection($classMethod);