Skip to content

Commit d027f19

Browse files
committed
Allow for other generators to be created
1 parent c3ae089 commit d027f19

File tree

11 files changed

+264
-48
lines changed

11 files changed

+264
-48
lines changed

Console/Command/GenerateCommand.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ protected function configure()
3030
$this->setName('yireo:test:generate')
3131
->setDescription('Generate tests for a given module')
3232
->addArgument('moduleName', InputArgument::REQUIRED, 'Module name')
33+
->addArgument('className', InputArgument::OPTIONAL, 'Class name')
3334
->addOption('override-existing', null, InputOption::VALUE_OPTIONAL, 'Override existing tests', false)
3435
->addOption('type', null, InputOption::VALUE_OPTIONAL, 'Type of tests (unit, integration)', 'integration')
3536
;
@@ -62,12 +63,26 @@ protected function execute(InputInterface $input, OutputInterface $output): int
6263
return Command::INVALID;
6364
}
6465

66+
$className = (string)$input->getArgument('className');
67+
68+
if ($type === 'integration' && !empty($className)) {
69+
$this->integrationTestGenerator->generateTest($moduleName, $className, $output, $overrideExisting);
70+
return Command::SUCCESS;
71+
}
72+
6573
if ($type === 'integration') {
66-
$this->integrationTestGenerator->generate($moduleName, $output, $overrideExisting);
74+
$this->integrationTestGenerator->generateAll($moduleName, $output, $overrideExisting);
75+
return Command::SUCCESS;
76+
}
77+
78+
if ($type === 'unit' && !empty($className)) {
79+
$this->unitTestGenerator->generateTest($moduleName, $className, $output, $overrideExisting);
80+
return Command::SUCCESS;
6781
}
6882

6983
if ($type === 'unit') {
70-
$this->unitTestGenerator->generate($moduleName, $output, $overrideExisting);
84+
$this->unitTestGenerator->generateAll($moduleName, $output, $overrideExisting);
85+
return Command::SUCCESS;
7186
}
7287

7388
return Command::SUCCESS;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Yireo\TestGenerator\Generator\IntegrationTest;
4+
5+
use Yireo\TestGenerator\Generator\PhpGeneratorFactory;
6+
use Yireo\TestGenerator\Generator\PhpGenerator;
7+
use Yireo\TestGenerator\Model\ClassStub;
8+
use Yireo\IntegrationTestHelper\Test\Integration\Traits\GetObjectManager;
9+
10+
abstract class AbstractTestGenerator implements TestGeneratorInterface
11+
{
12+
public function __construct(
13+
protected PhpGeneratorFactory $phpGeneratorFactory,
14+
) {
15+
}
16+
17+
abstract public function apply(ClassStub $classStub): bool;
18+
19+
public function generate(ClassStub $classStub, ClassStub $testClassStub): PhpGenerator
20+
{
21+
$phpGenerator = $this->getPhpGenerator($testClassStub);
22+
$phpGenerator->addTrait(GetObjectManager::class);
23+
$phpGenerator->addUse($classStub->getFullQualifiedClassName());
24+
25+
return $phpGenerator;
26+
}
27+
28+
protected function getPhpGenerator(ClassStub $testClassStub): PhpGenerator
29+
{
30+
return $this->phpGeneratorFactory->create($testClassStub->getClassName(), $testClassStub->getNamespace());
31+
}
32+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Yireo\TestGenerator\Generator\IntegrationTest;
4+
5+
use Magento\TestFramework\Fixture\Config as ConfigFixture;
6+
use ReflectionMethod;
7+
use Yireo\TestGenerator\Generator\PhpGenerator;
8+
use Yireo\TestGenerator\Model\ClassStub;
9+
10+
class ConfigTestGenerator extends AbstractTestGenerator
11+
{
12+
public function apply(ClassStub $classStub): bool
13+
{
14+
return str_ends_with($classStub->getFullQualifiedClassName(), 'Config\\Config');
15+
}
16+
17+
public function generate(ClassStub $classStub, ClassStub $testClassStub): PhpGenerator
18+
{
19+
$phpGenerator = parent::generate($classStub, $testClassStub);
20+
$phpGenerator->addUse(ConfigFixture::class, 'ConfigFixture');
21+
22+
foreach ($classStub->getClassMethods() as $classMethod) {
23+
if ($classMethod->isConstructor()) {
24+
continue;
25+
}
26+
27+
$methodName = $classMethod->getName();
28+
$methodName = preg_replace('/^get/', '', $methodName);
29+
$path = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $methodName));
30+
31+
$phpGenerator->addClassMethod(
32+
'test'.ucfirst($classMethod->getName()),
33+
$this->getTestConfigMethod($classStub, $classMethod)
34+
)->addAttribute(ConfigFixture::class, [
35+
'path' => $path,
36+
'value' => 'foobar',
37+
]);
38+
}
39+
40+
return $phpGenerator;
41+
}
42+
43+
private function getTestConfigMethod(ClassStub $classStub, ReflectionMethod $method): string
44+
{
45+
$className = $classStub->getClassName();
46+
$methodName = $method->getName();
47+
48+
return <<<EOF
49+
\$config = \$this->om()->get({$className}::class);
50+
\$this->assertSame('foobar', \$config->{$methodName}());
51+
// @todo: Insert the correct configuration test
52+
EOF;
53+
}
54+
}

Generator/IntegrationTest/GenericTestGenerator.php

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,23 @@
22

33
namespace Yireo\TestGenerator\Generator\IntegrationTest;
44

5-
use Yireo\TestGenerator\Generator\PhpGeneratorFactory;
5+
use Yireo\TestGenerator\Generator\PhpGenerator;
66
use Yireo\TestGenerator\Model\ClassStub;
7-
use Yireo\IntegrationTestHelper\Test\Integration\Traits\GetObjectManager;
87

9-
class GenericTestGenerator
8+
class GenericTestGenerator extends AbstractTestGenerator
109
{
11-
public function __construct(
12-
private PhpGeneratorFactory $phpGeneratorFactory,
13-
) {
10+
public function apply(ClassStub $classStub): bool
11+
{
12+
return true;
1413
}
1514

16-
public function generate(ClassStub $classStub, ClassStub $testClassStub): string
15+
public function generate(ClassStub $classStub, ClassStub $testClassStub): PhpGenerator
1716
{
18-
$testClassName = $testClassStub->getClassName();
19-
20-
$phpGenerator = $this->phpGeneratorFactory->create($testClassName, $testClassStub->getNamespace());
21-
$phpGenerator->addTrait(GetObjectManager::class);
22-
$phpGenerator->addUse($classStub->getFullQualifiedClassName());
17+
$phpGenerator = parent::generate($classStub, $testClassStub);
2318

2419
$phpGenerator->addClassMethod('testIfInstantiationWorks', $this->getTestIfInstantiationWorks($classStub->getClassName()));
2520

26-
return $phpGenerator->output();
21+
return $phpGenerator;
2722
}
2823

2924
private function getTestIfInstantiationWorks(string $className): string

Generator/IntegrationTest/ModuleTestGenerator.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Yireo\IntegrationTestHelper\Test\Integration\Traits\AssertModuleIsRegistered;
77
use Yireo\IntegrationTestHelper\Test\Integration\Traits\AssertModuleIsRegisteredForReal;
88
use Yireo\TestGenerator\Generator\PhpGeneratorFactory;
9+
use Yireo\TestGenerator\Generator\PhpGenerator;
910

1011
class ModuleTestGenerator
1112
{
@@ -14,15 +15,15 @@ public function __construct(
1415
) {
1516
}
1617

17-
public function generate(string $moduleName, string $classNamePrefix): string
18+
public function generate(string $moduleName, string $classNamePrefix): PhpGenerator
1819
{
1920
$phpGenerator = $this->phpGeneratorFactory->create('ModuleTest', $classNamePrefix);
2021
$phpGenerator->addTrait(AssertModuleIsEnabled::class);
2122
$phpGenerator->addTrait(AssertModuleIsRegistered::class);
2223
$phpGenerator->addTrait(AssertModuleIsRegisteredForReal::class);
2324
$phpGenerator->addClassMethod('testModule', $this->getMethodModuleTest($moduleName));
2425

25-
return $phpGenerator->output();
26+
return $phpGenerator;
2627
}
2728

2829
private function getMethodModuleTest(string $moduleName): string
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Yireo\TestGenerator\Generator\IntegrationTest;
4+
5+
use Yireo\TestGenerator\Generator\PhpGenerator;
6+
use Yireo\TestGenerator\Model\ClassStub;
7+
8+
interface TestGeneratorInterface
9+
{
10+
public function apply(ClassStub $classStub): bool;
11+
12+
public function generate(ClassStub $classStub, ClassStub $testClassStub): PhpGenerator;
13+
}

Generator/IntegrationTestGenerator.php

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66
use Magento\Framework\Component\ComponentRegistrar;
77
use Magento\Framework\Filesystem;
88
use Magento\Framework\Filesystem\Directory\WriteInterface;
9+
use RuntimeException;
910
use Symfony\Component\Console\Output\OutputInterface;
11+
use Yireo\TestGenerator\Generator\IntegrationTest\AbstractTestGenerator;
1012
use Yireo\TestGenerator\Generator\IntegrationTest\GenericTestGenerator;
1113
use Yireo\TestGenerator\Generator\IntegrationTest\ModuleTestGenerator;
14+
use Yireo\TestGenerator\Generator\IntegrationTest\TestGeneratorInterface;
15+
use Yireo\TestGenerator\Model\ClassStub;
1216
use Yireo\TestGenerator\Model\ClassStubFactory;
1317
use Yireo\TestGenerator\Utilities\ClassCollector;
1418

@@ -21,13 +25,17 @@ public function __construct(
2125
private DirectoryList $directoryList,
2226
private Filesystem $filesystem,
2327
private ClassCollector $classCollector,
24-
private ClassStubFactory $classStubFactory
28+
private ClassStubFactory $classStubFactory,
29+
private array $testGenerators = [],
2530
) {
2631
}
2732

28-
public function generate(string $moduleName, OutputInterface $output, bool $overrideExisting)
29-
{
30-
$modulePath = $this->componentRegistrar->getPath(ComponentRegistrar::MODULE, $moduleName);
33+
public function generateAll(
34+
string $moduleName,
35+
OutputInterface $output,
36+
bool $overrideExisting
37+
) {
38+
$modulePath = $this->getModulePath($moduleName);
3139
$testPath = $modulePath.'/Test/Integration/';
3240
if (false === $this->getWriter()->isExist($testPath)) {
3341
$this->getWriter()->create($testPath);
@@ -37,25 +45,43 @@ public function generate(string $moduleName, OutputInterface $output, bool $over
3745

3846
$testFile = $testPath.'ModuleTest.php';
3947
if (true === $overrideExisting || false === $this->getWriter()->isExist($testFile)) {
40-
$testContents = $this->moduleTestGenerator->generate($moduleName, $classNamePrefix);
48+
$phpGenerator = $this->moduleTestGenerator->generate($moduleName, $classNamePrefix);
49+
$testContents = $phpGenerator->output();
4150
$output->writeln('Generating module test');
4251
$this->getWriter()->writeFile($testFile, $testContents);
4352
}
4453

4554
$classNames = $this->classCollector->collect($modulePath);
4655
foreach ($classNames as $className) {
56+
$this->generateTest($className, $modulePath, $output, $overrideExisting);
57+
}
58+
}
4759

48-
$classStub = $this->classStubFactory->create($moduleName, $className);
49-
$testClassStub = $this->classStubFactory->createTest($classStub);
50-
$testFile = $modulePath.'/'.$testClassStub->getRelativePath();
60+
public function generateTest(
61+
string $moduleName,
62+
string $className,
63+
OutputInterface $output,
64+
bool $overrideExisting
65+
): void {
66+
$modulePath = $this->getModulePath($moduleName);
5167

52-
if (true === $overrideExisting || false === $this->getWriter()->isExist($testFile)) {
53-
$testContents = $this->genericTestGenerator->generate($classStub, $testClassStub);
54-
$output->writeln('Generating test for '.$className);
55-
$output->writeln('Writing file '.$testFile, OutputInterface::VERBOSITY_VERBOSE);
56-
$this->getWriter()->writeFile($testFile, $testContents);
57-
}
68+
$classStub = $this->classStubFactory->create($moduleName, $className);
69+
$testClassStub = $this->classStubFactory->createTest($classStub);
70+
$testFile = $modulePath.'/'.$testClassStub->getRelativePath();
71+
72+
if (false === $overrideExisting && $this->getWriter()->isExist($testFile)) {
73+
$output->writeln('Test for '.$className.' already exists');
74+
75+
return;
5876
}
77+
78+
$testGenerator = $this->getTestGenerator($classStub);
79+
$phpGenerator = $testGenerator->generate($classStub, $testClassStub);
80+
$testContents = $phpGenerator->output();
81+
82+
$output->writeln('Generating test for '.$className);
83+
$output->writeln('Writing file '.$testFile, OutputInterface::VERBOSITY_VERBOSE);
84+
$this->getWriter()->writeFile($testFile, $testContents);
5985
}
6086

6187
private function getClassNamePrefix(string $moduleName): string
@@ -69,4 +95,29 @@ private function getWriter(): WriteInterface
6995
{
7096
return $this->filesystem->getDirectoryWrite($this->directoryList::ROOT);
7197
}
98+
99+
private function getModulePath(string $moduleName): string
100+
{
101+
$modulePath = $this->componentRegistrar->getPath(ComponentRegistrar::MODULE, $moduleName);
102+
if (empty($modulePath)) {
103+
throw new RuntimeException('No path found for module "'.$moduleName.'"');
104+
}
105+
106+
return $modulePath;
107+
}
108+
109+
private function getTestGenerator(ClassStub $classStub): TestGeneratorInterface
110+
{
111+
foreach ($this->testGenerators as $testGenerator) {
112+
if (false === $testGenerator instanceof TestGeneratorInterface) {
113+
continue;
114+
}
115+
116+
if ($testGenerator->apply($classStub)) {
117+
return $testGenerator;
118+
}
119+
}
120+
121+
return $this->genericTestGenerator;
122+
}
72123
}

Generator/PhpGenerator.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Magento\Framework\Filesystem\Directory\WriteInterface;
66
use Nette\PhpGenerator\ClassType;
7+
use Nette\PhpGenerator\Method;
78
use Nette\PhpGenerator\PhpFile;
89
use Nette\PhpGenerator\PhpNamespace;
910
use Nette\PhpGenerator\PsrPrinter;
@@ -18,9 +19,11 @@ public function __construct(
1819
) {
1920
}
2021

21-
public function addClassMethod(string $methodName, string $methodBody)
22-
{
23-
$this->classType->addMethod($methodName)
22+
public function addClassMethod(
23+
string $methodName,
24+
string $methodBody,
25+
): Method {
26+
return $this->classType->addMethod($methodName)
2427
->setFinal()
2528
->setPublic()
2629
->setBody($methodBody);
@@ -32,9 +35,9 @@ public function addTrait(string $traitName)
3235
$this->addUse($traitName);
3336
}
3437

35-
public function addUse(string $namespace)
38+
public function addUse(string $namespace, ?string $alias = null)
3639
{
37-
$this->namespace->addUse($namespace);
40+
$this->namespace->addUse($namespace, $alias);
3841
}
3942

4043
public function generate(string $file):bool

0 commit comments

Comments
 (0)