From 8935229f534155026926e49dc8be0df2d49634e2 Mon Sep 17 00:00:00 2001 From: Alex Skrypnyk Date: Tue, 10 Dec 2024 07:49:20 +1100 Subject: [PATCH] [#97] Updated tests to use the application tester. Closes #97 --- src/app.php | 2 + .../Functional/AbstractFunctionalTestCase.php | 159 ++++-------------- tests/phpunit/Functional/BranchModeTest.php | 28 +-- .../phpunit/Functional/ForcePushModeTest.php | 42 ++--- tests/phpunit/Functional/GeneralTest.php | 97 ++++++----- tests/phpunit/Functional/TagTest.php | 6 +- tests/phpunit/Traits/ConsoleTrait.php | 105 ++++++++++++ tests/phpunit/Traits/FixtureTrait.php | 19 +++ 8 files changed, 255 insertions(+), 203 deletions(-) create mode 100644 tests/phpunit/Traits/ConsoleTrait.php diff --git a/src/app.php b/src/app.php index a597f7e..2df3357 100644 --- a/src/app.php +++ b/src/app.php @@ -10,6 +10,7 @@ use DrevOps\GitArtifact\Commands\ArtifactCommand; use Symfony\Component\Console\Application; +// @codeCoverageIgnoreStart $application = new Application(); $command = new ArtifactCommand(); @@ -17,3 +18,4 @@ $application->setDefaultCommand((string) $command->getName(), TRUE); $application->run(); +// @codeCoverageIgnoreEnd diff --git a/tests/phpunit/Functional/AbstractFunctionalTestCase.php b/tests/phpunit/Functional/AbstractFunctionalTestCase.php index b434b44..74ab592 100644 --- a/tests/phpunit/Functional/AbstractFunctionalTestCase.php +++ b/tests/phpunit/Functional/AbstractFunctionalTestCase.php @@ -5,18 +5,16 @@ namespace DrevOps\GitArtifact\Tests\Functional; use DrevOps\GitArtifact\Commands\ArtifactCommand; +use DrevOps\GitArtifact\Tests\Traits\ConsoleTrait; use DrevOps\GitArtifact\Tests\Traits\FixtureTrait; use DrevOps\GitArtifact\Tests\Traits\GitTrait; use DrevOps\GitArtifact\Tests\Unit\AbstractUnitTestCase; use DrevOps\GitArtifact\Traits\FilesystemTrait; -use PHPUnit\Framework\AssertionFailedError; -use Symfony\Component\Console\Application; -use Symfony\Component\Console\Output\ConsoleOutput; -use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Filesystem\Filesystem; abstract class AbstractFunctionalTestCase extends AbstractUnitTestCase { + use ConsoleTrait; use FilesystemTrait; use FixtureTrait; use GitTrait; @@ -36,55 +34,31 @@ abstract class AbstractFunctionalTestCase extends AbstractUnitTestCase { protected $dst; /** - * Artifact command. - */ - protected ArtifactCommand $command; - - /** - * Fixture directory. - * - * @var string + * Remote name. */ - protected $fixtureDir; + protected string $remoteName; /** * Current branch. - * - * @var string */ - protected $currentBranch; + protected string $currentBranch; /** * Artifact branch. - * - * @var string - */ - protected $artifactBranch; - - /** - * Remote name. - * - * @var string */ - protected $remoteName; + protected string $artifactBranch; /** - * Mode in which the build will run. - * - * Passed as a value of the --mode option. - * - * @var string + * Mode in which the artifact application will run. */ - protected $mode; + protected ?string $mode = NULL; /** * Current timestamp to run commands with. * * Used for generating internal tokens that could be based on time. - * - * @var int */ - protected $now; + protected int $now; /** * {@inheritdoc} @@ -94,7 +68,8 @@ protected function setUp(): void { $this->fs = new Filesystem(); - $this->fixtureDir = $this->fsGetAbsolutePath(sys_get_temp_dir() . DIRECTORY_SEPARATOR . date('U') . DIRECTORY_SEPARATOR . 'git_artifact'); + $this->fixtureInit('git_artifact'); + $this->fixtureDir = $this->fsGetAbsolutePath($this->fixtureDir); $this->src = $this->fsGetAbsolutePath($this->fixtureDir . DIRECTORY_SEPARATOR . 'src'); $this->gitInitRepo($this->src); @@ -109,6 +84,8 @@ protected function setUp(): void { $this->currentBranch = $this->gitGetGlobalDefaultBranch(); $this->artifactBranch = $this->currentBranch . '-artifact'; $this->remoteName = 'dst'; + + $this->consoleInitApplicationTester(ArtifactCommand::class); } /** @@ -133,9 +110,10 @@ protected function tearDown(): void { * @return string * Command output. */ - protected function assertCommandSuccess(?array $args = [], string $branch = 'testbranch', string $commit = 'Deployment commit'): string { + protected function assertArtifactCommandSuccess(?array $args = [], string $branch = 'testbranch', string $commit = 'Deployment commit'): string { $args += ['--branch' => 'testbranch']; - $output = $this->runCommand($args); + + $output = $this->runArtifactCommand($args); $this->assertStringNotContainsString('[error]', $output); $this->assertStringContainsString(sprintf('Pushed branch "%s" with commit message "%s"', $branch, $commit), $output); @@ -158,9 +136,10 @@ protected function assertCommandSuccess(?array $args = [], string $branch = 'tes * @return string * Command output. */ - protected function assertCommandFailure(?array $args = [], string $commit = 'Deployment commit'): string { + protected function assertArtifactCommandFailure(?array $args = [], string $commit = 'Deployment commit'): string { $args += ['--branch' => 'testbranch']; - $output = $this->runCommand($args, TRUE); + + $output = $this->runArtifactCommand($args, TRUE); $this->assertStringNotContainsString(sprintf('Pushed branch "%s" with commit message "%s"', $args['--branch'], $commit), $output); $this->assertStringNotContainsString('Deployment finished successfully.', $output); @@ -173,100 +152,34 @@ protected function assertCommandFailure(?array $args = [], string $commit = 'Dep * Run artifact build. * * @param array $args - * Additional arguments or options as an associative array. + * Additional arguments or options as an associative array. If NULL, no + * additional arguments are passed. * @param bool $expect_fail * Expect on fail. * * @return string * Output string. */ - protected function runCommand(?array $args = [], bool $expect_fail = FALSE): string { - try { - - if (is_null($args)) { - $input = []; - } - else { - $input = [ - '--root' => $this->fixtureDir, - '--now' => $this->now, - '--src' => $this->src, - 'remote' => $this->dst, - ]; - - if ($this->mode) { - $input['--mode'] = $this->mode; - } - - $input += $args; - } - - $this->runExecute(ArtifactCommand::class, $input); - $output = $this->commandTester->getDisplay(); - - if ($this->commandTester->getStatusCode() !== 0) { - throw new \Exception(sprintf("Command exited with non-zero code.\nThe output was:\n%s\nThe error output was:\n%s", $this->commandTester->getDisplay(), $this->commandTester->getErrorOutput())); - } - - if ($expect_fail) { - throw new AssertionFailedError(sprintf("Command exited successfully but should not.\nThe output was:\n%s\nThe error output was:\n%s", $this->commandTester->getDisplay(), $this->commandTester->getErrorOutput())); - } - - } - catch (\RuntimeException $exception) { - if (!$expect_fail) { - throw new AssertionFailedError('Command exited with an error:' . PHP_EOL . $exception->getMessage()); - } - $output = $exception->getMessage(); + protected function runArtifactCommand(?array $args = [], bool $expect_fail = FALSE): string { + if (is_null($args)) { + $input = []; } - catch (\Exception $exception) { - if (!$expect_fail) { - throw new AssertionFailedError('Command exited with an error:' . PHP_EOL . $exception->getMessage()); + else { + $input = [ + '--root' => $this->fixtureDir, + '--now' => $this->now, + '--src' => $this->src, + 'remote' => $this->dst, + ]; + + if ($this->mode) { + $input['--mode'] = $this->mode; } - } - - return $output; - } - - /** - * CommandTester instance. - * - * @var \Symfony\Component\Console\Tester\CommandTester - */ - protected $commandTester; - - /** - * Run main() with optional arguments. - * - * @param string|object $object_or_class - * Object or class name. - * @param array $input - * Optional array of input arguments. - * @param array $options - * Optional array of options. See CommandTester::execute() for details. - */ - protected function runExecute(string|object $object_or_class, array $input = [], array $options = []): void { - $application = new Application(); - /** @var \Symfony\Component\Console\Command\Command $instance */ - $instance = is_object($object_or_class) ? $object_or_class : new $object_or_class(); - $application->add($instance); - - $name = $instance->getName(); - if (empty($name)) { - /** @var string $name */ - $name = $this->getProtectedValue($instance, 'defaultName'); - } - - $command = $application->find($name); - $this->commandTester = new CommandTester($command); - $options['capture_stderr_separately'] = TRUE; - if (array_key_exists('-vvv', $input)) { - $options['verbosity'] = ConsoleOutput::VERBOSITY_DEBUG; - unset($input['-vvv']); + $input += $args; } - $this->commandTester->execute($input, $options); + return $this->consoleApplicationRun($input, [], $expect_fail); } } diff --git a/tests/phpunit/Functional/BranchModeTest.php b/tests/phpunit/Functional/BranchModeTest.php index dbba544..c6f2016 100644 --- a/tests/phpunit/Functional/BranchModeTest.php +++ b/tests/phpunit/Functional/BranchModeTest.php @@ -16,16 +16,16 @@ class BranchModeTest extends AbstractFunctionalTestCase { * {@inheritdoc} */ protected function setUp(): void { - $this->mode = 'branch'; + $this->mode = ArtifactCommand::MODE_BRANCH; parent::setUp(); } public function testBuild(): void { $this->gitCreateFixtureCommits(2); - $output = $this->assertCommandSuccess(); + $output = $this->assertArtifactCommandSuccess(); $this->assertStringContainsString('WARNING! Provided branch name does not have a token', $output); - $this->assertStringContainsString('Mode: branch', $output); + $this->assertStringContainsString('Mode: ' . ArtifactCommand::MODE_BRANCH, $output); $this->assertStringContainsString('Will push: Yes', $output); $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Deployment commit']); @@ -34,12 +34,12 @@ public function testBuild(): void { public function testBuildMoreCommitsSameBranch(): void { $this->gitCreateFixtureCommits(2); - $this->assertCommandSuccess(); + $this->assertArtifactCommandSuccess(); $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Deployment commit']); $this->gitCreateFixtureCommits(3, 2); - $this->assertCommandFailure(); + $this->assertArtifactCommandFailure(); // Make sure that broken artifact was not pushed. $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Deployment commit']); @@ -50,7 +50,7 @@ public function testBuildMoreCommits(): void { $this->now = time() - rand(1, 10 * 60); $branch1 = 'testbranch-' . date('Y-m-d_H-i-s', $this->now); - $output = $this->assertCommandSuccess(['--branch' => 'testbranch-[timestamp:Y-m-d_H-i-s]'], $branch1); + $output = $this->assertArtifactCommandSuccess(['--branch' => 'testbranch-[timestamp:Y-m-d_H-i-s]'], $branch1); $this->assertStringContainsString('Remote branch: ' . $branch1, $output); $this->assertStringNotContainsString('WARNING! Provided branch name does not have a token', $output); @@ -60,7 +60,7 @@ public function testBuildMoreCommits(): void { $this->now = time() - rand(1, 10 * 60); $branch2 = 'testbranch-' . date('Y-m-d_H-i-s', $this->now); - $output = $this->assertCommandSuccess(['--branch' => 'testbranch-[timestamp:Y-m-d_H-i-s]'], $branch2); + $output = $this->assertArtifactCommandSuccess(['--branch' => 'testbranch-[timestamp:Y-m-d_H-i-s]'], $branch2); $this->assertStringContainsString('Remote branch: ' . $branch2, $output); $this->gitAssertFixtureCommits(5, $this->dst, $branch2, ['Deployment commit']); @@ -71,7 +71,7 @@ public function testBuildMoreCommits(): void { public function testCleanupAfterSuccess(): void { $this->gitCreateFixtureCommits(2); - $this->assertCommandSuccess(); + $this->assertArtifactCommandSuccess(); $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Deployment commit']); $this->gitAssertCurrentBranch($this->src, $this->currentBranch); @@ -81,12 +81,12 @@ public function testCleanupAfterSuccess(): void { public function testCleanupAfterFailure(): void { $this->gitCreateFixtureCommits(2); - $this->assertCommandSuccess(); + $this->assertArtifactCommandSuccess(); $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Deployment commit']); $this->gitCreateFixtureCommits(3, 2); // Trigger erroneous build by pushing to the same branch. - $this->assertCommandFailure(); + $this->assertArtifactCommandFailure(); $this->gitAssertCurrentBranch($this->src, $this->currentBranch); $this->gitAssertRemoteNotExists($this->src, $this->remoteName); @@ -99,7 +99,7 @@ public function testGitignore(): void { $this->now = time() - rand(1, 10 * 60); $branch1 = 'testbranch-' . date('Y-m-d_H-i-s', $this->now); - $this->assertCommandSuccess(['--branch' => 'testbranch-[timestamp:Y-m-d_H-i-s]'], $branch1); + $this->assertArtifactCommandSuccess(['--branch' => 'testbranch-[timestamp:Y-m-d_H-i-s]'], $branch1); $this->gitAssertFixtureCommits(2, $this->dst, $branch1, ['Deployment commit']); $this->assertFileDoesNotExist($this->dst . DIRECTORY_SEPARATOR . 'f3'); @@ -109,7 +109,7 @@ public function testGitignore(): void { $this->gitCommitAll($this->src, 'Commit number 3'); $this->now = time() - rand(1, 10 * 60); $branch2 = 'testbranch-' . date('Y-m-d_H-i-s', $this->now); - $this->assertCommandSuccess(['--branch' => 'testbranch-[timestamp:Y-m-d_H-i-s]'], $branch2); + $this->assertArtifactCommandSuccess(['--branch' => 'testbranch-[timestamp:Y-m-d_H-i-s]'], $branch2); $this->gitAssertFixtureCommits(3, $this->dst, $branch2, ['Deployment commit']); @@ -125,7 +125,7 @@ public function testGitignoreCustom(): void { $this->now = time() - rand(1, 10 * 60); $branch1 = 'testbranch-' . date('Y-m-d_H-i-s', $this->now); - $this->assertCommandSuccess([ + $this->assertArtifactCommandSuccess([ '--branch' => 'testbranch-[timestamp:Y-m-d_H-i-s]', '--gitignore' => $this->src . DIRECTORY_SEPARATOR . 'mygitignore', ], $branch1); @@ -139,7 +139,7 @@ public function testGitignoreCustom(): void { $this->gitCommitAll($this->src, 'Commit number 3'); $this->now = time() - rand(1, 10 * 60); $branch2 = 'testbranch-' . date('Y-m-d_H-i-s', $this->now); - $this->assertCommandSuccess(['--branch' => 'testbranch-[timestamp:Y-m-d_H-i-s]'], $branch2); + $this->assertArtifactCommandSuccess(['--branch' => 'testbranch-[timestamp:Y-m-d_H-i-s]'], $branch2); $this->gitAssertFixtureCommits(3, $this->dst, $branch2, ['Deployment commit']); diff --git a/tests/phpunit/Functional/ForcePushModeTest.php b/tests/phpunit/Functional/ForcePushModeTest.php index b7e5a77..74541a1 100644 --- a/tests/phpunit/Functional/ForcePushModeTest.php +++ b/tests/phpunit/Functional/ForcePushModeTest.php @@ -18,15 +18,15 @@ class ForcePushModeTest extends AbstractFunctionalTestCase { protected function setUp(): void { - $this->mode = 'force-push'; + $this->mode = ArtifactCommand::MODE_FORCE_PUSH; parent::setUp(); } public function testBuild(): void { $this->gitCreateFixtureCommits(2); - $output = $this->assertCommandSuccess(); - $this->assertStringContainsString('Mode: force-push', $output); + $output = $this->assertArtifactCommandSuccess(); + $this->assertStringContainsString('Mode: ' . ArtifactCommand::MODE_FORCE_PUSH, $output); $this->assertStringContainsString('Will push: Yes', $output); $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Deployment commit']); @@ -35,12 +35,12 @@ public function testBuild(): void { public function testBuildMoreCommits(): void { $this->gitCreateFixtureCommits(2); - $this->assertCommandSuccess(); + $this->assertArtifactCommandSuccess(); $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Deployment commit']); $this->gitCreateFixtureCommits(3, 2); - $this->assertCommandSuccess(); + $this->assertArtifactCommandSuccess(); $this->gitAssertFixtureCommits(5, $this->dst, 'testbranch', ['Deployment commit']); } @@ -48,10 +48,10 @@ public function testBuildMoreCommits(): void { public function testIdempotence(): void { $this->gitCreateFixtureCommits(2); - $this->assertCommandSuccess(); + $this->assertArtifactCommandSuccess(); $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Deployment commit']); - $this->assertCommandSuccess(); + $this->assertArtifactCommandSuccess(); $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Deployment commit']); } @@ -75,7 +75,7 @@ public function testSubRepos(): void { $this->gitAssertFilesNotExist($this->src, ['r2/r21.git/index']); $this->gitAssertFilesNotExist($this->src, ['r3/r31/r311/.git/index']); - $output = $this->assertCommandSuccess(['-vvv' => TRUE]); + $output = $this->assertArtifactCommandSuccess(['-vvv' => TRUE]); $this->assertStringContainsString(sprintf('Removing sub-repository "%s"', $this->fsGetAbsolutePath($this->src . DIRECTORY_SEPARATOR . 'r1/.git')), $output); $this->assertStringContainsString(sprintf('Removing sub-repository "%s"', $this->fsGetAbsolutePath($this->src . DIRECTORY_SEPARATOR . 'r2/r21/.git')), $output); $this->assertStringContainsString(sprintf('Removing sub-repository "%s"', $this->fsGetAbsolutePath($this->src . DIRECTORY_SEPARATOR . 'r3/r31/r311/.git')), $output); @@ -95,7 +95,7 @@ public function testSubRepos(): void { public function testCleanupAfterSuccess(): void { $this->gitCreateFixtureCommits(2); - $this->assertCommandSuccess(); + $this->assertArtifactCommandSuccess(); $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Deployment commit']); $this->gitAssertCurrentBranch($this->src, $this->currentBranch); @@ -105,7 +105,7 @@ public function testCleanupAfterSuccess(): void { public function testCleanupAfterFailure(): void { $this->gitCreateFixtureCommits(1); - $output = $this->assertCommandFailure(['--branch' => '*invalid']); + $output = $this->assertArtifactCommandFailure(['--branch' => '*invalid']); $this->assertStringContainsString('Incorrect value "*invalid" specified for git remote branch', $output); $this->gitAssertCurrentBranch($this->src, $this->currentBranch); @@ -117,7 +117,7 @@ public function testGitignore(): void { $this->gitCreateFixtureCommits(2); $this->fixtureCreateFile($this->src, 'f3'); - $this->assertCommandSuccess(); + $this->assertArtifactCommandSuccess(); $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Deployment commit']); $this->gitAssertFilesNotExist($this->dst, 'f3'); @@ -125,7 +125,7 @@ public function testGitignore(): void { // Now, remove the .gitignore and push again. $this->fixtureRemoveFile($this->src, '.gitignore'); $this->gitCommitAll($this->src, 'Commit number 3'); - $this->assertCommandSuccess(); + $this->assertArtifactCommandSuccess(); $this->gitAssertFixtureCommits(3, $this->dst, 'testbranch', ['Deployment commit']); } @@ -136,7 +136,7 @@ public function testGitignoreCustom(): void { $this->fixtureCreateFile($this->src, 'mygitignore', 'uic'); - $this->assertCommandSuccess(['--gitignore' => $this->src . DIRECTORY_SEPARATOR . 'mygitignore']); + $this->assertArtifactCommandSuccess(['--gitignore' => $this->src . DIRECTORY_SEPARATOR . 'mygitignore']); $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Deployment commit']); $this->gitAssertFilesNotExist($this->dst, 'uic'); @@ -150,7 +150,7 @@ public function testGitignoreCustom(): void { $this->fixtureCreateFile($this->src, 'uic'); $this->fixtureRemoveFile($this->src, 'mygitignore'); $this->gitCommitAll($this->src, 'Commit number 3'); - $this->assertCommandSuccess(); + $this->assertArtifactCommandSuccess(); $this->gitAssertFixtureCommits(3, $this->dst, 'testbranch', ['Deployment commit'], FALSE); $this->gitAssertFilesCommitted($this->dst, ['f1', 'f2', 'uic'], 'testbranch'); @@ -174,7 +174,7 @@ public function testGitignoreCustomRemoveCommittedFiles(): void { $this->fixtureCreateFile($this->src, 'mygitignore', ['f1', 'ii', 'ci', 'ui']); - $this->assertCommandSuccess(['--gitignore' => $this->src . DIRECTORY_SEPARATOR . 'mygitignore']); + $this->assertArtifactCommandSuccess(['--gitignore' => $this->src . DIRECTORY_SEPARATOR . 'mygitignore']); $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Custom third commit', 'Deployment commit'], FALSE); $this->gitAssertFilesCommitted($this->dst, ['.gitignore', 'f2', 'ic', 'd/cc', 'uc'], 'testbranch'); @@ -235,7 +235,7 @@ public function testGitignoreCustomAllowlisting(): void { ]); // Run the build. - $this->assertCommandSuccess([ + $this->assertArtifactCommandSuccess([ '-vvv' => TRUE, '--gitignore' => $this->src . DIRECTORY_SEPARATOR . 'mygitignore', ]); @@ -271,7 +271,7 @@ public function testBuildTag(): void { $this->gitCreateFixtureCommits(2); $this->gitAddTag($this->src, 'tag1'); - $this->assertCommandSuccess(['--branch' => '[tags]'], 'tag1'); + $this->assertArtifactCommandSuccess(['--branch' => '[tags]'], 'tag1'); $this->gitAssertFixtureCommits(2, $this->dst, 'tag1', ['Deployment commit']); } @@ -281,12 +281,12 @@ public function testBuildMultipleTags(): void { $this->gitAddTag($this->src, 'tag1'); $this->gitAddTag($this->src, 'tag2'); - $this->assertCommandSuccess(['--branch' => '[tags]'], 'tag1-tag2'); + $this->assertArtifactCommandSuccess(['--branch' => '[tags]'], 'tag1-tag2'); $this->gitAssertFixtureCommits(2, $this->dst, 'tag1-tag2', ['Deployment commit']); $this->gitCreateFixtureCommit(3); $this->gitAddTag($this->src, 'tag3'); - $this->assertCommandSuccess(['--branch' => '[tags]'], 'tag3'); + $this->assertArtifactCommandSuccess(['--branch' => '[tags]'], 'tag3'); $this->gitAssertFixtureCommits(3, $this->dst, 'tag3', ['Deployment commit']); } @@ -295,7 +295,7 @@ public function testBuildMultipleTagsMissingTags(): void { $this->gitAddTag($this->src, 'tag1'); $this->gitCreateFixtureCommit(3); - $this->assertCommandFailure(['--branch' => '[tags]']); + $this->assertArtifactCommandFailure(['--branch' => '[tags]']); } public function testBuildMultipleTagsDelimiter(): void { @@ -303,7 +303,7 @@ public function testBuildMultipleTagsDelimiter(): void { $this->gitAddTag($this->src, 'tag1'); $this->gitAddTag($this->src, 'tag2'); - $this->assertCommandSuccess(['--branch' => '[tags:__]'], 'tag1__tag2'); + $this->assertArtifactCommandSuccess(['--branch' => '[tags:__]'], 'tag1__tag2'); $this->gitAssertFixtureCommits(2, $this->dst, 'tag1__tag2', ['Deployment commit']); } diff --git a/tests/phpunit/Functional/GeneralTest.php b/tests/phpunit/Functional/GeneralTest.php index ba9e46e..3c2049c 100644 --- a/tests/phpunit/Functional/GeneralTest.php +++ b/tests/phpunit/Functional/GeneralTest.php @@ -12,18 +12,27 @@ #[CoversClass(ArtifactGitRepository::class)] class GeneralTest extends AbstractFunctionalTestCase { + public function testHelp(): void { + $output = $this->runArtifactCommand(['--help' => TRUE]); + + $this->assertStringContainsString('artifact [options] [--] ', $output); + $this->assertStringContainsString('Assemble a code artifact from your codebase, remove unnecessary files, and push it into a separate Git repository.', $output); + } + public function testCompulsoryParameter(): void { $this->dst = ''; - $output = $this->runCommand(['remote' => ' '], TRUE); + $output = $this->runArtifactCommand(['remote' => ' '], TRUE); $this->assertStringContainsString('Remote argument must be a non-empty string', $output); } public function testInfo(): void { $this->gitCreateFixtureCommits(1); - $output = $this->runCommand(['--dry-run' => TRUE]); + + $output = $this->runArtifactCommand(['--dry-run' => TRUE]); + $this->assertStringContainsString('Artifact information', $output); - $this->assertStringContainsString('Mode: force-push', $output); + $this->assertStringContainsString('Mode: ' . ArtifactCommand::MODE_FORCE_PUSH, $output); $this->assertStringContainsString('Source repository: ' . $this->src, $output); $this->assertStringContainsString('Remote repository: ' . $this->dst, $output); $this->assertStringContainsString('Remote branch: ' . $this->currentBranch, $output); @@ -38,7 +47,8 @@ public function testInfo(): void { public function testShowChanges(): void { $this->gitCreateFixtureCommits(1); - $output = $this->runCommand([ + + $output = $this->runArtifactCommand([ '--show-changes' => TRUE, '--dry-run' => TRUE, ]); @@ -51,7 +61,8 @@ public function testShowChanges(): void { public function testNoCleanup(): void { $this->gitCreateFixtureCommits(1); - $output = $this->runCommand([ + + $output = $this->runArtifactCommand([ '--no-cleanup' => TRUE, '--dry-run' => TRUE, ]); @@ -63,14 +74,15 @@ public function testNoCleanup(): void { public function testDebug(): void { $this->gitCreateFixtureCommits(1); - $output = $this->runCommand([ + + $output = $this->runArtifactCommand([ '-vvv' => TRUE, '--dry-run' => TRUE, ]); $this->assertStringContainsString('Debug messages enabled', $output); $this->assertStringContainsString('Artifact information', $output); - $this->assertStringContainsString('Mode: force-push', $output); + $this->assertStringContainsString('Mode: ' . ArtifactCommand::MODE_FORCE_PUSH, $output); $this->assertStringContainsString('Source repository: ' . $this->src, $output); $this->assertStringContainsString('Remote repository: ' . $this->dst, $output); $this->assertStringContainsString('Remote branch: ' . $this->currentBranch, $output); @@ -92,51 +104,52 @@ public function testDebugLogFile(): void { $report = $this->src . DIRECTORY_SEPARATOR . 'report.txt'; $this->gitCreateFixtureCommits(1); - $commandOutput = $this->runCommand([ + $output = $this->runArtifactCommand([ '--dry-run' => TRUE, '--log' => $report, ]); - $this->assertStringContainsString('Debug messages enabled', $commandOutput); - $this->assertStringContainsString('Artifact information', $commandOutput); - $this->assertStringContainsString('Mode: force-push', $commandOutput); - $this->assertStringContainsString('Source repository: ' . $this->src, $commandOutput); - $this->assertStringContainsString('Remote repository: ' . $this->dst, $commandOutput); - $this->assertStringContainsString('Remote branch: ' . $this->currentBranch, $commandOutput); - $this->assertStringContainsString('Gitignore file: No', $commandOutput); - $this->assertStringContainsString('Will push: No', $commandOutput); - - $this->assertStringContainsString('Artifact report', $commandOutput); - $this->assertStringContainsString(sprintf('Source repository: %s', $this->src), $commandOutput); - $this->assertStringContainsString(sprintf('Remote repository: %s', $this->dst), $commandOutput); - $this->assertStringContainsString(sprintf('Remote branch: %s', $this->currentBranch), $commandOutput); - $this->assertStringContainsString('Gitignore file: No', $commandOutput); - $this->assertStringContainsString('Push result: Success', $commandOutput); + $this->assertStringContainsString('Debug messages enabled', $output); + $this->assertStringContainsString('Artifact information', $output); + $this->assertStringContainsString('Mode: ' . ArtifactCommand::MODE_FORCE_PUSH, $output); + $this->assertStringContainsString('Source repository: ' . $this->src, $output); + $this->assertStringContainsString('Remote repository: ' . $this->dst, $output); + $this->assertStringContainsString('Remote branch: ' . $this->currentBranch, $output); + $this->assertStringContainsString('Gitignore file: No', $output); + $this->assertStringContainsString('Will push: No', $output); + + $this->assertStringContainsString('Artifact report', $output); + $this->assertStringContainsString(sprintf('Source repository: %s', $this->src), $output); + $this->assertStringContainsString(sprintf('Remote repository: %s', $this->dst), $output); + $this->assertStringContainsString(sprintf('Remote branch: %s', $this->currentBranch), $output); + $this->assertStringContainsString('Gitignore file: No', $output); + $this->assertStringContainsString('Push result: Success', $output); $this->assertFileExists($report); - $output = file_get_contents($report); - - $this->assertStringContainsString('Debug messages enabled', (string) $output); - $this->assertStringContainsString('Artifact information', (string) $output); - $this->assertStringContainsString('Mode: force-push', (string) $output); - $this->assertStringContainsString('Source repository: ' . $this->src, (string) $output); - $this->assertStringContainsString('Remote repository: ' . $this->dst, (string) $output); - $this->assertStringContainsString('Remote branch: ' . $this->currentBranch, (string) $output); - $this->assertStringContainsString('Gitignore file: No', (string) $output); - $this->assertStringContainsString('Will push: No', (string) $output); - $this->assertStringNotContainsString('Added changes:', (string) $output); - - $this->assertStringContainsString('Artifact report', (string) $output); - $this->assertStringContainsString(sprintf('Source repository: %s', $this->src), (string) $output); - $this->assertStringContainsString(sprintf('Remote repository: %s', $this->dst), (string) $output); - $this->assertStringContainsString(sprintf('Remote branch: %s', $this->currentBranch), (string) $output); - $this->assertStringContainsString('Gitignore file: No', (string) $output); - $this->assertStringContainsString('Push result: Success', (string) $output); + $report_output = file_get_contents($report); + + $this->assertStringContainsString('Debug messages enabled', (string) $report_output); + $this->assertStringContainsString('Artifact information', (string) $report_output); + $this->assertStringContainsString('Mode: ' . ArtifactCommand::MODE_FORCE_PUSH, (string) $report_output); + $this->assertStringContainsString('Source repository: ' . $this->src, (string) $report_output); + $this->assertStringContainsString('Remote repository: ' . $this->dst, (string) $report_output); + $this->assertStringContainsString('Remote branch: ' . $this->currentBranch, (string) $report_output); + $this->assertStringContainsString('Gitignore file: No', (string) $report_output); + $this->assertStringContainsString('Will push: No', (string) $report_output); + $this->assertStringNotContainsString('Added changes:', (string) $report_output); + + $this->assertStringContainsString('Artifact report', (string) $report_output); + $this->assertStringContainsString(sprintf('Source repository: %s', $this->src), (string) $report_output); + $this->assertStringContainsString(sprintf('Remote repository: %s', $this->dst), (string) $report_output); + $this->assertStringContainsString(sprintf('Remote branch: %s', $this->currentBranch), (string) $report_output); + $this->assertStringContainsString('Gitignore file: No', (string) $report_output); + $this->assertStringContainsString('Push result: Success', (string) $report_output); } public function testDebugDisabled(): void { $this->gitCreateFixtureCommits(1); - $output = $this->runCommand(['--dry-run' => TRUE]); + + $output = $this->runArtifactCommand(['--dry-run' => TRUE]); $this->assertStringNotContainsString('Debug messages enabled', $output); diff --git a/tests/phpunit/Functional/TagTest.php b/tests/phpunit/Functional/TagTest.php index 7f09366..dbc7cbd 100644 --- a/tests/phpunit/Functional/TagTest.php +++ b/tests/phpunit/Functional/TagTest.php @@ -17,7 +17,7 @@ class TagTest extends AbstractFunctionalTestCase { * {@inheritdoc} */ protected function setUp(): void { - $this->mode = 'force-push'; + $this->mode = ArtifactCommand::MODE_FORCE_PUSH; parent::setUp(); } @@ -29,8 +29,8 @@ public function testDetachedTag(): void { $repo = (new Git())->open($this->src); $branches = $repo->getBranches(); - $output = $this->assertCommandSuccess(); - $this->assertStringContainsString('Mode: force-push', $output); + $output = $this->assertArtifactCommandSuccess(); + $this->assertStringContainsString('Mode: ' . ArtifactCommand::MODE_FORCE_PUSH, $output); $this->assertStringContainsString('Will push: Yes', $output); $this->gitAssertFixtureCommits(2, $this->dst, 'testbranch', ['Deployment commit']); diff --git a/tests/phpunit/Traits/ConsoleTrait.php b/tests/phpunit/Traits/ConsoleTrait.php new file mode 100644 index 0000000..905a14e --- /dev/null +++ b/tests/phpunit/Traits/ConsoleTrait.php @@ -0,0 +1,105 @@ +add($instance); + + $name = $instance->getName(); + if (empty($name)) { + $ret = $this->getProtectedValue($instance, 'defaultName'); + if (!empty($ret) || !is_string($ret)) { + throw new \InvalidArgumentException('The provided object does not have a valid name'); + } + $name = $ret; + } + + $application->setDefaultCommand($name, $is_single_command); + + $application->setAutoExit(FALSE); + $application->setCatchExceptions(FALSE); + if (method_exists($application, 'setCatchErrors')) { + $application->setCatchErrors(FALSE); + } + + $this->appTester = new ApplicationTester($application); + } + + /** + * Run console application. + * + * @param array $input + * Input arguments. + * @param array $options + * Options. + * @param bool $expect_fail + * Whether a failure is expected. Defaults to FALSE. + * + * @return string + * Run output (stdout or stderr). + */ + protected function consoleApplicationRun(array $input = [], array $options = [], bool $expect_fail = FALSE): string { + $options += ['capture_stderr_separately' => TRUE]; + + try { + $this->appTester->run($input, $options); + $output = $this->appTester->getDisplay(); + + if ($this->appTester->getStatusCode() !== 0) { + throw new \Exception(sprintf("Application exited with non-zero code.\nThe output was:\n%s\nThe error output was:\n%s", $this->appTester->getDisplay(), $this->appTester->getErrorOutput())); + } + + if ($expect_fail) { + throw new AssertionFailedError(sprintf("Application exited successfully but should not.\nThe output was:\n%s\nThe error output was:\n%s", $this->appTester->getDisplay(), $this->appTester->getErrorOutput())); + } + } + catch (\RuntimeException $exception) { + if (!$expect_fail) { + throw new AssertionFailedError('Application exited with an error:' . PHP_EOL . $exception->getMessage()); + } + $output = $exception->getMessage(); + } + catch (\Exception $exception) { + if (!$expect_fail) { + throw new AssertionFailedError('Application exited with an error:' . PHP_EOL . $exception->getMessage()); + } + } + + return $output; + } + +} diff --git a/tests/phpunit/Traits/FixtureTrait.php b/tests/phpunit/Traits/FixtureTrait.php index 201008c..e65df6d 100644 --- a/tests/phpunit/Traits/FixtureTrait.php +++ b/tests/phpunit/Traits/FixtureTrait.php @@ -13,6 +13,25 @@ */ trait FixtureTrait { + /** + * Fixture directory. + */ + protected string $fixtureDir; + + /** + * Initialize fixture directory. + * + * @param string|null $name + * Optional fixture name. + * @param string|null $root + * Optional root directory. + */ + public function fixtureInit(?string $name, ?string $root = NULL): void { + $name = $name ?? get_class($this); + $root = $root ?? sys_get_temp_dir(); + $this->fixtureDir = $root . DIRECTORY_SEPARATOR . date('U') . DIRECTORY_SEPARATOR . $name; + } + /** * Create fixture file at provided path. *