From 2881a2b66b61178bd9b03d68222de5d6c4ee3c19 Mon Sep 17 00:00:00 2001 From: Ondrej Machulda Date: Mon, 30 Nov 2020 01:46:31 +0100 Subject: [PATCH] Extract exceptions assembling from the code into custom Exceptions to clean it a bit --- src-tests/Component/LegacyTest.php | 17 ++--- .../Command/GenerateTimelineCommandTest.php | 4 +- .../Console/Command/ResultsCommandTest.php | 4 +- .../Command/RunCommandIntegrationTest.php | 1 + src-tests/Console/Command/RunCommandTest.php | 4 +- src-tests/Process/ProcessSetCreatorTest.php | 12 ++-- src-tests/Process/ProcessSetTest.php | 10 +-- src-tests/Process/ProcessWrapperTest.php | 12 ++-- .../Utils/Annotations/ClassParserTest.php | 10 ++- src/Component/Legacy.php | 19 ++--- src/Component/LegacyException.php | 10 --- .../Command/GenerateTimelineCommand.php | 10 +-- src/Console/Command/ResultsCommand.php | 10 +-- src/Console/Command/RunCommand.php | 9 +-- src/Exception/LegacyComponentException.php | 10 +++ src/Exception/LogicException.php | 38 ++++++++++ src/Exception/RuntimeException.php | 69 +++++++++++++++++++ src/Exception/StewardExceptionInterface.php | 7 ++ src/Process/ProcessSet.php | 21 ++---- src/Process/ProcessSetCreator.php | 34 ++++----- src/Process/ProcessWrapper.php | 8 ++- src/Utils/Annotations/ClassParser.php | 12 +--- 22 files changed, 214 insertions(+), 117 deletions(-) delete mode 100644 src/Component/LegacyException.php create mode 100644 src/Exception/LegacyComponentException.php create mode 100644 src/Exception/LogicException.php create mode 100644 src/Exception/RuntimeException.php create mode 100644 src/Exception/StewardExceptionInterface.php diff --git a/src-tests/Component/LegacyTest.php b/src-tests/Component/LegacyTest.php index ed55978c..3352a678 100644 --- a/src-tests/Component/LegacyTest.php +++ b/src-tests/Component/LegacyTest.php @@ -4,12 +4,13 @@ use Lmc\Steward\Component\Fixtures\StringableObject; use Lmc\Steward\ConfigHelper; +use Lmc\Steward\Exception\LegacyComponentException; use Lmc\Steward\Test\AbstractTestCase; use PHPUnit\Framework\TestCase; /** * @covers \Lmc\Steward\Component\Legacy - * @covers \Lmc\Steward\Component\LegacyException + * @covers \Lmc\Steward\Exception\LegacyComponentException */ class LegacyTest extends TestCase { @@ -35,7 +36,7 @@ public function testShouldThrowExceptionIfLegacyFileNotFound(): void $legacy = new Legacy($this->testCase); $this->expectOutputRegex('/.*New Legacy instantiated.*/'); - $this->expectException(LegacyException::class); + $this->expectException(LegacyComponentException::class); $this->expectExceptionMessage('Cannot read Legacy file'); $legacy->loadWithName('not-existing'); @@ -50,7 +51,7 @@ public function testShouldFailIfNotUnserializableFileFound(): void $legacy->setFileDir(sys_get_temp_dir()); $this->expectOutputRegex('/.*New Legacy instantiated.*/'); - $this->expectException(LegacyException::class); + $this->expectException(LegacyComponentException::class); $this->expectExceptionMessage('Cannot parse Legacy from file'); $legacy->loadWithName('wrong'); @@ -98,7 +99,7 @@ public function testShouldFailIfSavingToNotExistingDirectory(): void $this->expectOutputRegex('/.*Saving data as Legacy "baz" to file "\/notexisting\/baz\.legacy".*/'); - $this->expectException(LegacyException::class); + $this->expectException(LegacyComponentException::class); $this->expectExceptionMessage('Cannot save Legacy to file /notexisting/baz.legacy'); $legacy->saveWithName([], 'baz'); @@ -146,7 +147,7 @@ public function testShouldFailIfTryingToAutomaticallySaveLegacyIfTestDoesntHaveP $legacy = new Legacy($testCasePhase1); $legacy->setFileDir(sys_get_temp_dir()); - $this->expectException(LegacyException::class); + $this->expectException(LegacyComponentException::class); $this->expectExceptionMessage( 'Cannot generate Legacy name from class without \'Phase\' followed by number in name' ); @@ -223,11 +224,11 @@ public function testShouldAutomaticallySaveAndLoadLegacyForMethodsWithSameNameIn try { $legacy2Method2->load(Legacy::LEGACY_TYPE_TEST); - } catch (LegacyException $e) { - $this->assertContains('Cannot read Legacy file', $e->getMessage()); + } catch (LegacyComponentException $e) { + $this->assertStringContainsString('Cannot read Legacy file', $e->getMessage()); return; } - $this->fail('Expected exception LegacyException not thrown when loading Legacy that should not exists'); + $this->fail('Expected exception LegacyComponentException not thrown when loading Legacy that should not exists'); } } diff --git a/src-tests/Console/Command/GenerateTimelineCommandTest.php b/src-tests/Console/Command/GenerateTimelineCommandTest.php index 17b1ce33..902c9d47 100644 --- a/src-tests/Console/Command/GenerateTimelineCommandTest.php +++ b/src-tests/Console/Command/GenerateTimelineCommandTest.php @@ -3,6 +3,7 @@ namespace Lmc\Steward\Console\Command; use Lmc\Steward\Console\Application; +use Lmc\Steward\Exception\RuntimeException; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; @@ -11,6 +12,7 @@ /** * @covers \Lmc\Steward\Console\Command\GenerateTimelineCommand + * @covers \Lmc\Steward\Exception\RuntimeException */ class GenerateTimelineCommandTest extends TestCase { @@ -33,7 +35,7 @@ protected function setUp(): void public function testShouldShowErrorIfResultsFileCannotBeFound(): void { - $this->expectException(\RuntimeException::class); + $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Cannot read results file "/not/accessible.xml"'); $this->tester->execute( diff --git a/src-tests/Console/Command/ResultsCommandTest.php b/src-tests/Console/Command/ResultsCommandTest.php index d1c6ed0a..2ed72653 100644 --- a/src-tests/Console/Command/ResultsCommandTest.php +++ b/src-tests/Console/Command/ResultsCommandTest.php @@ -3,6 +3,7 @@ namespace Lmc\Steward\Console\Command; use Lmc\Steward\Console\Application; +use Lmc\Steward\Exception\RuntimeException; use Lmc\Steward\LineEndingsNormalizerTrait; use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Output\OutputInterface; @@ -11,6 +12,7 @@ /** * @covers \Lmc\Steward\Console\Command\ResultsCommand + * @covers \Lmc\Steward\Exception\RuntimeException */ class ResultsCommandTest extends TestCase { @@ -35,7 +37,7 @@ protected function setUp(): void public function testShouldShowErrorIfResultsFileCannotBeFound(): void { - $this->expectException(\RuntimeException::class); + $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Cannot read results file "/not/accessible.xml"'); $this->tester->execute( diff --git a/src-tests/Console/Command/RunCommandIntegrationTest.php b/src-tests/Console/Command/RunCommandIntegrationTest.php index 17931408..968ba87c 100644 --- a/src-tests/Console/Command/RunCommandIntegrationTest.php +++ b/src-tests/Console/Command/RunCommandIntegrationTest.php @@ -12,6 +12,7 @@ * Run command tests that require real Selenium server to execute the tests. * * @covers \Lmc\Steward\Console\Command\RunCommand + * @covers \Lmc\Steward\Exception\RuntimeException * @covers \Lmc\Steward\Listener\WebDriverListener * @covers \Lmc\Steward\Process\ExecutionLoop * @group integration diff --git a/src-tests/Console/Command/RunCommandTest.php b/src-tests/Console/Command/RunCommandTest.php index b9c04fbe..5e1b8104 100644 --- a/src-tests/Console/Command/RunCommandTest.php +++ b/src-tests/Console/Command/RunCommandTest.php @@ -7,6 +7,7 @@ use Lmc\Steward\Console\CommandEvents; use Lmc\Steward\Console\Event\BasicConsoleEvent; use Lmc\Steward\Console\Event\ExtendedConsoleEvent; +use Lmc\Steward\Exception\RuntimeException; use Lmc\Steward\Process\ProcessSet; use Lmc\Steward\Process\ProcessSetCreator; use Lmc\Steward\Process\ProcessWrapper; @@ -20,6 +21,7 @@ /** * @covers \Lmc\Steward\Console\Command\RunCommand + * @covers \Lmc\Steward\Exception\RuntimeException * @covers \Lmc\Steward\Process\ExecutionLoop */ class RunCommandTest extends TestCase @@ -145,7 +147,7 @@ public function testShouldThrowExceptionOnlyIfUnsupportedBrowserSelected( $this->command->setSeleniumAdapter($seleniumAdapterMock); if ($shouldThrowException) { - $this->expectException(\RuntimeException::class); + $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Browser "' . $browserName . '" is not supported'); } diff --git a/src-tests/Process/ProcessSetCreatorTest.php b/src-tests/Process/ProcessSetCreatorTest.php index 3ff7fab9..e56f3f6d 100644 --- a/src-tests/Process/ProcessSetCreatorTest.php +++ b/src-tests/Process/ProcessSetCreatorTest.php @@ -7,6 +7,8 @@ use Lmc\Steward\Console\Configuration\ConfigOptions; use Lmc\Steward\Console\Configuration\ConfigResolver; use Lmc\Steward\Console\Event\RunTestsProcessEvent; +use Lmc\Steward\Exception\LogicException; +use Lmc\Steward\Exception\RuntimeException; use Lmc\Steward\Process\Fixtures\DelayedTests\DelayedByZeroTimeTest; use Lmc\Steward\Process\Fixtures\DelayedTests\DelayedTest; use Lmc\Steward\Process\Fixtures\DelayedTests\FirstTest; @@ -24,6 +26,8 @@ use Symfony\Component\OptionsResolver\OptionsResolver; /** + * @covers \Lmc\Steward\Exception\LogicException + * @covers \Lmc\Steward\Exception\RuntimeException * @covers \Lmc\Steward\Process\ProcessSetCreator */ class ProcessSetCreatorTest extends TestCase @@ -124,7 +128,7 @@ public function testShouldThrowExceptionIfAddingClassWithNameMismatchingTheFileN { $files = $this->findDummyTests('WrongClassTest.php', 'InvalidTests'); - $this->expectException(\RuntimeException::class); + $this->expectException(RuntimeException::class); $this->expectExceptionMessageRegExp( '/Error loading class "Lmc\\\\Steward\\\\Process\\\\Fixtures\\\\InvalidTests\\\\ReallyWrongClassTest"' . ' from file ".*WrongClassTest.php"/' @@ -213,10 +217,10 @@ public function testShouldThrowExceptionIfAddingTestWithDelayTimeButWithoutDelay { $files = $this->findDummyTests('InvalidDelayTest.php', 'InvalidTests'); - $this->expectException(\InvalidArgumentException::class); + $this->expectException(LogicException::class); $this->expectExceptionMessage( - 'Testcase "Lmc\Steward\Process\Fixtures\InvalidTests\InvalidDelayTest" has defined delay 5 minutes, ' - . 'but doesn\'t have defined the testcase to run after' + 'Testcase "Lmc\Steward\Process\Fixtures\InvalidTests\InvalidDelayTest" has defined @delayMinutes 5 minutes, ' + . 'but doesn\'t have defined the testcase to run after using @delayAfter' ); $this->creator->createFromFiles($files, [], []); diff --git a/src-tests/Process/ProcessSetTest.php b/src-tests/Process/ProcessSetTest.php index 59d5ff03..188397af 100644 --- a/src-tests/Process/ProcessSetTest.php +++ b/src-tests/Process/ProcessSetTest.php @@ -4,6 +4,8 @@ use Assert\InvalidArgumentException; use Graphp\Algorithms\Tree\OutTree; +use Lmc\Steward\Exception\LogicException; +use Lmc\Steward\Exception\RuntimeException; use Lmc\Steward\Process\Fixtures\MockOrderStrategy; use Lmc\Steward\Publisher\XmlPublisher; use PHPUnit\Framework\TestCase; @@ -33,7 +35,7 @@ public function testShouldFailWhenAddingTestWithNonUniqueName(): void { $this->set->add(new ProcessWrapper(new Process(''), 'Foo\Bar')); - $this->expectException(\InvalidArgumentException::class); + $this->expectException(RuntimeException::class); $this->expectExceptionMessage('Testcase with name "Foo\Bar" was already added'); $this->set->add(new ProcessWrapper(new Process(''), 'Foo\Bar')); @@ -201,9 +203,9 @@ public function testShouldFailBuildingTreeIfTestHasDependencyOnNotExistingTest() $this->set->add($process); - $this->expectException(\InvalidArgumentException::class); + $this->expectException(LogicException::class); $this->expectExceptionMessage( - 'Testcase "Foo" has @delayAfter dependency on "NotExisting", but this testcase was not defined.' + 'Testcase "Foo" has @delayAfter dependency on "NotExisting", but this testcase is not defined.' ); $this->set->buildTree(); } @@ -224,7 +226,7 @@ public function testShouldFailBuildingTreeIfCycleDetected(): void $this->set->add($processA); $this->set->add($processB); - $this->expectException(\InvalidArgumentException::class); + $this->expectException(LogicException::class); $this->expectExceptionMessage('Cannot build tree graph from tests dependencies.'); $this->set->buildTree(); diff --git a/src-tests/Process/ProcessWrapperTest.php b/src-tests/Process/ProcessWrapperTest.php index 9b0c0883..54901eb9 100644 --- a/src-tests/Process/ProcessWrapperTest.php +++ b/src-tests/Process/ProcessWrapperTest.php @@ -72,15 +72,17 @@ public function provideInvalidDelay(): array return [ 'negative value' => [ -5, - 'Delay defined in testcase "Foo" must be greater than or equal 0, but "-5" was given', + 'Delay defined in testcase "Foo" using @delayMinutes must be greater than or equal 0, ' + . 'but "-5" was given', ], 'string value' => [ 'omg', - 'Delay defined in testcase "Foo" must be greater than or equal 0, but "omg" was given', + 'Delay defined in testcase "Foo" using @delayMinutes must be greater than or equal 0, ' + . 'but "omg" was given', ], 'empty value' => [ '', - 'Delay defined in testcase "Foo" must be greater than or equal 0, but "" was given', + 'Delay defined in testcase "Foo" using @delayMinutes must be greater than or equal 0, but "" was given', ], ]; } @@ -90,7 +92,9 @@ public function testShouldFailIfDependencyWasDefinedButWithoutDelay(): void $wrapper = new ProcessWrapper(new Process(''), 'Foo'); $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Testcase "Foo" should run after "Bar", but no delay was defined'); + $this->expectExceptionMessage( + 'Testcase "Foo" should run after "Bar", but no delay was defined using @delayMinutes' + ); $wrapper->setDelay('Bar', null); } diff --git a/src-tests/Utils/Annotations/ClassParserTest.php b/src-tests/Utils/Annotations/ClassParserTest.php index 21195be4..2ef6272a 100644 --- a/src-tests/Utils/Annotations/ClassParserTest.php +++ b/src-tests/Utils/Annotations/ClassParserTest.php @@ -2,11 +2,13 @@ namespace Lmc\Utils\Annotations; +use Lmc\Steward\Exception\RuntimeException; use Lmc\Steward\Utils\Annotations\ClassParser; use PHPUnit\Framework\TestCase; use Symfony\Component\Finder\SplFileInfo; /** + * @covers \Lmc\Steward\Exception\RuntimeException * @covers \Lmc\Steward\Utils\Annotations\ClassParser */ class ClassParserTest extends TestCase @@ -24,8 +26,10 @@ public function testShouldThrowExceptionForMultipleClassesInOneFile(): void { $file = $this->createFileInfo('MultipleClassesInFile.php'); - $this->expectException(\RuntimeException::class); - $this->expectExceptionMessageRegExp('/^File ".+MultipleClassesInFile.php" contains definition of 2 classes\./'); + $this->expectException(RuntimeException::class); + $this->expectExceptionMessageRegExp( + '/^File ".+MultipleClassesInFile.php" contains definition of 2 classes\./' + ); ClassParser::readClassNameFromFile($file); } @@ -33,7 +37,7 @@ public function testShouldThrowExceptionForNoClassInOneFile(): void { $file = $this->createFileInfo('NoClassInFile.php'); - $this->expectException(\RuntimeException::class); + $this->expectException(RuntimeException::class); $this->expectExceptionMessageRegExp('/^No class found in file ".+NoClassInFile.php"/'); ClassParser::readClassNameFromFile($file); } diff --git a/src/Component/Legacy.php b/src/Component/Legacy.php index 7dca4e19..cef36e43 100644 --- a/src/Component/Legacy.php +++ b/src/Component/Legacy.php @@ -53,6 +53,7 @@ namespace Lmc\Steward\Component; use Lmc\Steward\ConfigProvider; +use Lmc\Steward\Exception\LegacyComponentException; use Lmc\Steward\Test\AbstractTestCase; use Lmc\Steward\Utils\Strings; @@ -100,14 +101,14 @@ public function setFileDir(string $dir): void * * @param string $type LEGACY_TYPE_CASE (shared by all tests in test case) * or LEGACY_TYPE_TEST (shared only by the same test function) - * @throws LegacyException + * @throws LegacyComponentException */ protected function getLegacyName(string $type): string { $name = $this->testClassName; if (!preg_match('/Phase\d/', $name)) { - throw new LegacyException( + throw new LegacyComponentException( "Cannot generate Legacy name from class without 'Phase' followed by number in name " . $name ); } @@ -136,7 +137,7 @@ protected function getLegacyFullPath(string $filename): string * @param string $legacyName filename to store the data if null getLegacyFilename is called to generate filename * from the test class name * @param mixed $data - * @throws LegacyException + * @throws LegacyComponentException */ public function saveWithName($data, string $legacyName): void { @@ -145,7 +146,7 @@ public function saveWithName($data, string $legacyName): void $this->debug('Legacy data: %s', $this->getPrintableValue($data)); if (@file_put_contents($filename, serialize($data)) === false) { - throw new LegacyException('Cannot save Legacy to file ' . $filename); + throw new LegacyComponentException('Cannot save Legacy to file ' . $filename); } } @@ -155,7 +156,7 @@ public function saveWithName($data, string $legacyName): void * @param string $type LEGACY_TYPE_CASE (shared by all tests in test case) * or LEGACY_TYPE_TEST (shared only by the same test function) * @param mixed $data - * @throws LegacyException + * @throws LegacyComponentException */ public function save($data, string $type = self::LEGACY_TYPE_CASE): void { @@ -168,7 +169,7 @@ public function save($data, string $type = self::LEGACY_TYPE_CASE): void * * @param string $type LEGACY_TYPE_CASE (shared by all tests in test case) * or LEGACY_TYPE_TEST (shared only by the same test function) - * @throws LegacyException + * @throws LegacyComponentException */ public function load(string $type = self::LEGACY_TYPE_CASE) { @@ -180,7 +181,7 @@ public function load(string $type = self::LEGACY_TYPE_CASE) * Raises exception if it is not found. * * @param string $legacyName filename to store the data from the test class name - * @throws LegacyException + * @throws LegacyComponentException */ public function loadWithName(string $legacyName) { @@ -190,12 +191,12 @@ public function loadWithName(string $legacyName) $data = @file_get_contents($filename); if ($data === false) { - throw new LegacyException('Cannot read Legacy file ' . $filename); + throw new LegacyComponentException('Cannot read Legacy file ' . $filename); } $legacy = unserialize($data); if ($legacy === false) { - throw new LegacyException('Cannot parse Legacy from file ' . $filename); + throw new LegacyComponentException('Cannot parse Legacy from file ' . $filename); } $this->debug('Legacy data: %s', $this->getPrintableValue($legacy)); diff --git a/src/Component/LegacyException.php b/src/Component/LegacyException.php deleted file mode 100644 index 2c806ad3..00000000 --- a/src/Component/LegacyException.php +++ /dev/null @@ -1,10 +0,0 @@ -getOption(self::OPTION_RESULTS_FILE); if (!is_readable($inputResultsFilePath)) { - throw new \RuntimeException( - sprintf( - 'Cannot read results file "%s", make sure it is accessible ' - . '(or use --%s option if it is stored elsewhere)', - $inputResultsFilePath, - self::OPTION_RESULTS_FILE - ) - ); + throw RuntimeException::forNotAccessibleResultsFile($inputResultsFilePath, self::OPTION_RESULTS_FILE); } return $inputResultsFilePath; diff --git a/src/Console/Command/ResultsCommand.php b/src/Console/Command/ResultsCommand.php index 402c243b..82810118 100644 --- a/src/Console/Command/ResultsCommand.php +++ b/src/Console/Command/ResultsCommand.php @@ -4,6 +4,7 @@ use Lmc\Steward\Console\CommandEvents; use Lmc\Steward\Console\Event\BasicConsoleEvent; +use Lmc\Steward\Exception\RuntimeException; use Lmc\Steward\Process\ProcessWrapper; use Lmc\Steward\Publisher\AbstractPublisher; use Lmc\Steward\Publisher\XmlPublisher; @@ -61,14 +62,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $filePath = $input->getOption(self::OPTION_RESULTS_FILE); if (!is_readable($filePath)) { - throw new \RuntimeException( - sprintf( - 'Cannot read results file "%s", make sure it is accessible ' - . '(or use --%s option if it is stored elsewhere)', - $filePath, - self::OPTION_RESULTS_FILE - ) - ); + throw RuntimeException::forNotAccessibleResultsFile($filePath, self::OPTION_RESULTS_FILE); } $data = $this->processResults($filePath); diff --git a/src/Console/Command/RunCommand.php b/src/Console/Command/RunCommand.php index e684ab1e..5a3ce4ea 100644 --- a/src/Console/Command/RunCommand.php +++ b/src/Console/Command/RunCommand.php @@ -7,6 +7,7 @@ use Lmc\Steward\Console\Configuration\ConfigOptions; use Lmc\Steward\Console\Event\BasicConsoleEvent; use Lmc\Steward\Console\Event\ExtendedConsoleEvent; +use Lmc\Steward\Exception\RuntimeException; use Lmc\Steward\Process\ExecutionLoop; use Lmc\Steward\Process\MaxTotalDelayStrategy; use Lmc\Steward\Process\ProcessSetCreator; @@ -192,13 +193,7 @@ protected function initialize(InputInterface $input, OutputInterface $output): v // Check if browser is supported if (!isset($this->supportedBrowsers[$browserNormalized])) { - throw new \RuntimeException( - sprintf( - 'Browser "%s" is not supported (use one of: %s)', - $browserNormalized, - implode(', ', array_keys($this->supportedBrowsers)) - ) - ); + throw RuntimeException::forUnsupportedBrowser($browserNormalized, array_keys($this->supportedBrowsers)); } // Set WebDriver browser identifier back to the argument value diff --git a/src/Exception/LegacyComponentException.php b/src/Exception/LegacyComponentException.php new file mode 100644 index 00000000..791463f0 --- /dev/null +++ b/src/Exception/LegacyComponentException.php @@ -0,0 +1,10 @@ +getClassName(); if (isset($this->processes[$className])) { - throw new \InvalidArgumentException( - sprintf( - 'Testcase with name "%s" was already added, make sure you don\'t have duplicate class names.', - $className - ) - ); + throw RuntimeException::forDuplicateClassName($className); } $this->processes[$className] = $processWrapper; @@ -112,13 +109,7 @@ public function buildTree(): OutTree } else { // is dependant => link it to its dependency // Throw error if dependency is to not existing vertex if (!$this->graph->hasVertex($processWrapper->getDelayAfter())) { - throw new \InvalidArgumentException( - sprintf( - 'Testcase "%s" has @delayAfter dependency on "%s", but this testcase was not defined.', - $className, - $processWrapper->getDelayAfter() - ) - ); + throw LogicException::forDelayWithNotExistingTestcase($className, $processWrapper->getDelayAfter()); } $this->graph->getVertex($processWrapper->getDelayAfter()) @@ -131,9 +122,7 @@ public function buildTree(): OutTree $this->tree = new OutTree($this->graph); if (!$this->tree->isTree()) { - throw new \InvalidArgumentException( - sprintf('Cannot build tree graph from tests dependencies. Probably some cyclic dependency is present.') - ); + throw LogicException::forCyclicDependencyInGraph(); } return $this->tree; diff --git a/src/Process/ProcessSetCreator.php b/src/Process/ProcessSetCreator.php index 5918daee..3dcdfffc 100644 --- a/src/Process/ProcessSetCreator.php +++ b/src/Process/ProcessSetCreator.php @@ -6,6 +6,8 @@ use Lmc\Steward\Console\CommandEvents; use Lmc\Steward\Console\Configuration\ConfigOptions; use Lmc\Steward\Console\Event\RunTestsProcessEvent; +use Lmc\Steward\Exception\LogicException; +use Lmc\Steward\Exception\RuntimeException; use Lmc\Steward\Publisher\AbstractPublisher; use Lmc\Steward\Utils\Annotations\ClassAnnotations; use Lmc\Steward\Utils\Annotations\ClassParser; @@ -219,21 +221,18 @@ private function getExcludingGroups(array $excludeGroups, array $annotations): a private function setupProcessDelays(ProcessWrapper $processWrapper, array $annotations): void { - $delayAfter = !empty($annotations['delayAfter']) ? current($annotations['delayAfter']) : ''; + $delayAfterClass = !empty($annotations['delayAfter']) ? current($annotations['delayAfter']) : ''; $delayMinutes = !empty($annotations['delayMinutes']) ? current($annotations['delayMinutes']) : null; - if ($delayAfter) { - $processWrapper->setDelay($delayAfter, $delayMinutes); - } elseif ($delayMinutes !== null && empty($delayAfter)) { - throw new \InvalidArgumentException( - sprintf( - 'Testcase "%s" has defined delay %d minutes, ' - . 'but doesn\'t have defined the testcase to run after', - $processWrapper->getClassName(), - $delayMinutes - ) - ); + if ($delayMinutes !== null && empty($delayAfterClass)) { + throw LogicException::forDelayWithMissingTestcase($processWrapper->getClassName(), $delayMinutes); + } + + if ($delayAfterClass === '') { + return; } + + $processWrapper->setDelay($delayAfterClass, $delayMinutes); } /** @@ -244,16 +243,7 @@ private function getClassAnnotations(string $className, string $fileName): array try { return ClassAnnotations::getAnnotationsForClass($className); } catch (\ReflectionException $e) { - throw new \RuntimeException( - sprintf( - 'Error loading class "%s" from file "%s". Make sure the class name and namespace matches ' - . 'the file path.', - $className, - $fileName - ), - 0, - $e - ); + throw RuntimeException::forReflectionErrorWhenLoadedFromFile($className, $fileName, $e); } } } diff --git a/src/Process/ProcessWrapper.php b/src/Process/ProcessWrapper.php index d52a1da0..26feffe7 100644 --- a/src/Process/ProcessWrapper.php +++ b/src/Process/ProcessWrapper.php @@ -79,11 +79,15 @@ public function setDelay(string $afterClass, $minutes): void { Assertion::notNull( $minutes, - sprintf('Testcase "%s" should run after "%s", but no delay was defined', $this->getClassName(), $afterClass) + sprintf( + 'Testcase "%s" should run after "%s", but no delay was defined using @delayMinutes', + $this->getClassName(), + $afterClass + ) ); $assertionError = sprintf( - 'Delay defined in testcase "%s" must be greater than or equal 0, but "%s" was given', + 'Delay defined in testcase "%s" using @delayMinutes must be greater than or equal 0, but "%s" was given', $this->getClassName(), $minutes ); diff --git a/src/Utils/Annotations/ClassParser.php b/src/Utils/Annotations/ClassParser.php index 372ee1b4..3694cb69 100644 --- a/src/Utils/Annotations/ClassParser.php +++ b/src/Utils/Annotations/ClassParser.php @@ -2,6 +2,7 @@ namespace Lmc\Steward\Utils\Annotations; +use Lmc\Steward\Exception\RuntimeException; use Roave\BetterReflection\BetterReflection; use Roave\BetterReflection\Reflector\ClassReflector; use Roave\BetterReflection\SourceLocator\Type\SingleFileSourceLocator; @@ -24,18 +25,11 @@ public static function readClassNameFromFile(SplFileInfo $file): string private static function assertOneClassInFile(array $classesInFile, SplFileInfo $file): void { if (count($classesInFile) === 0) { - throw new \RuntimeException(sprintf('No class found in file "%s"', $file->getRelativePathname())); + throw RuntimeException::forNoClassInFile($file->getRelativePathname()); } if (count($classesInFile) > 1) { - throw new \RuntimeException( - sprintf( - 'File "%s" contains definition of %d classes. However, each class must be defined in its own' - . ' separate file.', - $file->getRelativePathname(), - count($classesInFile) - ) - ); + throw RuntimeException::forMultipleClassesInOneFile($file->getRelativePathname(), count($classesInFile)); } } }