From 873f9ba96d132bbbf697e9125de0461e1eb2559c Mon Sep 17 00:00:00 2001 From: Adam Elsodaney Date: Mon, 10 Jun 2024 18:20:35 +0100 Subject: [PATCH] Atomize namespace processing; Install full Sylius library to use as candidates. --- README.md | 11 ++++- composer.json | 6 +-- .../Pass/GlobalTestSubjectInstancePass.php | 29 ++++++++--- .../Pass/ImportMockingLibraryPass.php | 48 +++++++++++++++++++ ...acePass.php => ImportSubjectClassPass.php} | 44 +++++------------ lib/Transunit/Pass/MoveNamespacePass.php | 44 +++++++++++++++++ lib/Transunit/Transunit.php | 25 ++++++---- transunit.php | 1 + 8 files changed, 154 insertions(+), 54 deletions(-) create mode 100644 lib/Transunit/Pass/ImportMockingLibraryPass.php rename lib/Transunit/Pass/{NamespacePass.php => ImportSubjectClassPass.php} (61%) create mode 100644 lib/Transunit/Pass/MoveNamespacePass.php diff --git a/README.md b/README.md index 8356426..1132f99 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,11 @@ -# transunit +Transunit +=== + Convert PhpSpec tests to PHPUnit + +Dependencies +--- + + - nikic/php-parser + - symfony/finder + - symfony/filesystem diff --git a/composer.json b/composer.json index ed26a80..d2426bc 100644 --- a/composer.json +++ b/composer.json @@ -2,13 +2,11 @@ "require-dev": { "phpspec/phpspec": "*", "phpunit/phpunit": "*", - "sylius/addressing": "*", + "sylius/sylius": "^1.0", "phpspec/prophecy-phpunit": "^2.2" }, "require": { - "nikic/php-parser": "*", - "symfony/finder": "*", - "symfony/filesystem": "^7.0" + "nikic/php-parser": "*" }, "autoload": { "psr-4": { diff --git a/lib/Transunit/Pass/GlobalTestSubjectInstancePass.php b/lib/Transunit/Pass/GlobalTestSubjectInstancePass.php index e2e74a9..643b337 100644 --- a/lib/Transunit/Pass/GlobalTestSubjectInstancePass.php +++ b/lib/Transunit/Pass/GlobalTestSubjectInstancePass.php @@ -73,14 +73,29 @@ private function instantiateTestSubject(Node\Stmt\ClassMethod $node, string $sub foreach ($node->stmts as $stmt) { // Check if expression is a property assignment - if ($stmt instanceof Node\Stmt\Expression - && $stmt->expr instanceof Node\Expr\Assign - && $stmt->expr->var instanceof Node\Expr\PropertyFetch - && $stmt->expr->var->var instanceof Node\Expr\Variable - && $stmt->expr->var->var->name === 'this' - ) { - $collaboratorNames[$stmt->expr->var->name->name] = true; + if (! $stmt instanceof Node\Stmt\Expression) { + continue; + } + + if (! $stmt->expr instanceof Node\Expr\Assign) { + continue; + } + + if (! $stmt->expr->var instanceof Node\Expr\PropertyFetch) { + continue; } + + if (! $stmt->expr->var->var instanceof Node\Expr\Variable) { + continue; + } + + $collaboratorVariableName = $stmt->expr->var->var->name; + + if ($collaboratorVariableName === 'this') { + continue; + } + + $collaboratorNames[$collaboratorVariableName] = true; } $globalCollaborators = []; diff --git a/lib/Transunit/Pass/ImportMockingLibraryPass.php b/lib/Transunit/Pass/ImportMockingLibraryPass.php new file mode 100644 index 0000000..0d1e695 --- /dev/null +++ b/lib/Transunit/Pass/ImportMockingLibraryPass.php @@ -0,0 +1,48 @@ +findFirstInstanceOf($ast, Namespace_::class)]; + } + + public function rewrite(Node $node): void + { + if (!$node instanceof Namespace_) { + return; + } + + $this->importMockingLibraryClasses($node); + } + + private function importMockingLibraryClasses(Namespace_ $node): void + { + array_unshift($node->stmts, new Node\Stmt\Use_([ + new Node\Stmt\UseUse(new Name('Prophecy\Prophecy\ObjectProphecy')), + ])); + + array_unshift($node->stmts, new Node\Stmt\Use_([ + new Node\Stmt\UseUse(new Name('Prophecy\PhpUnit\ProphecyTrait')), + ])); + + array_unshift($node->stmts, new Node\Stmt\Use_([ + new Node\Stmt\UseUse(new Name('PHPUnit\Framework\TestCase')), + ])); + } +} diff --git a/lib/Transunit/Pass/NamespacePass.php b/lib/Transunit/Pass/ImportSubjectClassPass.php similarity index 61% rename from lib/Transunit/Pass/NamespacePass.php rename to lib/Transunit/Pass/ImportSubjectClassPass.php index 31c3a42..40c6613 100644 --- a/lib/Transunit/Pass/NamespacePass.php +++ b/lib/Transunit/Pass/ImportSubjectClassPass.php @@ -8,7 +8,17 @@ use PhpParser\NodeFinder; use Transunit\Pass; -class NamespacePass implements Pass +/** + * ``` + * namespace test\unit\Foo\Bar; + * + * + use Foo\Bar\TestSubject; + * + * class TestSubjectSpec extends ObjectBehaviour + * { + * ``` + */ +class ImportSubjectClassPass implements Pass { public function find(NodeFinder $nodeFinder, $ast): array { @@ -21,24 +31,7 @@ public function rewrite(Node $node): void return; } - $this->moveToNamespace($node); $this->importSubjectClass($node); - $this->importMockingLibraryClasses($node); - } - - /** - * namespace tests\unit\Foo\Bar; - */ - private function moveToNamespace(Namespace_ $node): void - { - $ns = $node->name->getParts(); - - if ($ns[0] === 'spec') { - array_shift($ns); - $ns = array_merge(['tests', 'unit'], $ns); - } - - $node->name = new Name($ns); } /** @@ -81,19 +74,4 @@ private function importSubjectClass(Namespace_ $node): void array_unshift($node->stmts, $use); } - - private function importMockingLibraryClasses(Namespace_ $node): void - { - array_unshift($node->stmts, new Node\Stmt\Use_([ - new Node\Stmt\UseUse(new Name('Prophecy\Prophecy\ObjectProphecy')), - ])); - - array_unshift($node->stmts, new Node\Stmt\Use_([ - new Node\Stmt\UseUse(new Name('Prophecy\PhpUnit\ProphecyTrait')), - ])); - - array_unshift($node->stmts, new Node\Stmt\Use_([ - new Node\Stmt\UseUse(new Name('PHPUnit\Framework\TestCase')), - ])); - } } diff --git a/lib/Transunit/Pass/MoveNamespacePass.php b/lib/Transunit/Pass/MoveNamespacePass.php new file mode 100644 index 0000000..0b52bed --- /dev/null +++ b/lib/Transunit/Pass/MoveNamespacePass.php @@ -0,0 +1,44 @@ +findFirstInstanceOf($ast, Namespace_::class)]; + } + + public function rewrite(Node $node): void + { + if (!$node instanceof Namespace_) { + return; + } + + $this->moveToNamespace($node); + } + + private function moveToNamespace(Namespace_ $node): void + { + $ns = $node->name->getParts(); + + if ($ns[0] === 'spec') { + array_shift($ns); + $ns = array_merge(['tests', 'unit'], $ns); + } + + $node->name = new Name($ns); + } +} diff --git a/lib/Transunit/Transunit.php b/lib/Transunit/Transunit.php index 0d2278b..9674720 100644 --- a/lib/Transunit/Transunit.php +++ b/lib/Transunit/Transunit.php @@ -12,22 +12,27 @@ class Transunit { - public static function run(string $path): void + public static function run(string $path, string $destination = 'var'): void { - $f = new Filesystem(); + $fs = new Filesystem(); $specs = (new Finder())->files()->in($path)->name('*Spec.php'); $root = dirname(__DIR__, 2); - $exportDir = "{$root}/var"; - $f->remove($exportDir); - $f->mkdir($exportDir); + $exportDir = "{$root}/{$destination}"; + + $fs->remove($exportDir); + $fs->mkdir($exportDir); foreach ($specs as $file) { + $relative = trim($fs->makePathRelative($file->getPath(), $path), DIRECTORY_SEPARATOR); $newFilename = substr($file->getBasename(), 0, -8) . 'Test.php'; + $fullPathToNewTestFile = "{$exportDir}/{$relative}/{$newFilename}"; + $modifiedCode = self::processFile($file->getRealPath()); - $fullPathToNewTestFile = "{$exportDir}/{$newFilename}"; - $f->touch($fullPathToNewTestFile); - file_put_contents($fullPathToNewTestFile, $modifiedCode); + + $fs->mkdir("{$exportDir}/{$relative}"); + $fs->touch($fullPathToNewTestFile); + $fs->dumpFile($fullPathToNewTestFile, $modifiedCode); } } @@ -49,7 +54,9 @@ private static function processFile(string $path): string $nodeFinder = new NodeFinder(); $passes = [ - new Pass\NamespacePass(), + new Pass\MoveNamespacePass(), + new Pass\ImportSubjectClassPass(), + new Pass\ImportMockingLibraryPass(), new Pass\ClassnamePass(), new Pass\GlobalCollaboratorPass(), new Pass\GlobalTestSubjectInstancePass(), diff --git a/transunit.php b/transunit.php index 9658734..e83beed 100644 --- a/transunit.php +++ b/transunit.php @@ -4,5 +4,6 @@ $args = $argv; array_shift($args); +$args[0] = getcwd().'/'.$args[0]; \Transunit\Transunit::run(...$args);