-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: introduce EveryTestHasSameNamespaceAsCoveredClass check (#38)
Replaces EveryTestHasSameNamespaceAsTestedClass check
- Loading branch information
Showing
16 changed files
with
357 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
113 changes: 113 additions & 0 deletions
113
src/TestCheck/EveryTestHasSameNamespaceAsCoveredClass.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Cdn77\TestUtils\TestCheck; | ||
|
||
use Cdn77\EntityFqnExtractor\ClassExtractor; | ||
use PHPUnit\Framework\TestCase; | ||
use ReflectionClass; | ||
|
||
use function class_exists; | ||
use function count; | ||
use function Safe\preg_match; | ||
use function Safe\preg_match_all; | ||
use function Safe\sprintf; | ||
use function Safe\substr; | ||
use function strlen; | ||
use function strpos; | ||
use function substr_replace; | ||
use function trait_exists; | ||
|
||
final class EveryTestHasSameNamespaceAsCoveredClass implements TestCheck | ||
{ | ||
private const PATTERN_COVERS = '~\* @covers(DefaultClass)? +(?<coveredClass>.+?)(?:\n| \*/)~'; | ||
private const PATTERN_COVERS_NOTHING = '~\* @coversNothing~'; | ||
|
||
private string $testsNamespaceSuffix; | ||
|
||
/** @param iterable<string> $filePathNames */ | ||
public function __construct(private iterable $filePathNames, string $testsNamespaceSuffix = 'Tests') | ||
{ | ||
$this->testsNamespaceSuffix = '\\' . $testsNamespaceSuffix . '\\'; | ||
} | ||
|
||
public function run(TestCase $testCaseContext): void | ||
{ | ||
$testCaseContext::assertTrue(true); | ||
|
||
foreach ($this->filePathNames as $file) { | ||
$classReflection = new ReflectionClass(ClassExtractor::get($file)); | ||
|
||
$docComment = $classReflection->getDocComment(); | ||
if ($docComment === false) { | ||
$docComment = ''; | ||
} | ||
|
||
$matchesCovers = preg_match_all(self::PATTERN_COVERS, $docComment, $coversMatches) > 0; | ||
$matchesCoversNothing = preg_match(self::PATTERN_COVERS_NOTHING, $docComment) === 1; | ||
|
||
if ($matchesCovers && $matchesCoversNothing) { | ||
$testCaseContext::fail(sprintf( | ||
'Test file "%s" contains both @covers and @coversNothing annotations.', | ||
$file | ||
)); | ||
} | ||
|
||
if ($matchesCoversNothing) { | ||
continue; | ||
} | ||
|
||
$className = $classReflection->getName(); | ||
$classNameWithoutSuffix = substr($className, 0, -4); | ||
$pos = strpos($classNameWithoutSuffix, $this->testsNamespaceSuffix); | ||
if ($pos === false) { | ||
$coveredClassName = $classNameWithoutSuffix; | ||
} else { | ||
$coveredClassName = substr_replace( | ||
$classNameWithoutSuffix, | ||
'\\', | ||
$pos, | ||
strlen($this->testsNamespaceSuffix) | ||
); | ||
} | ||
|
||
if (class_exists($coveredClassName) || trait_exists($coveredClassName)) { | ||
continue; | ||
} | ||
|
||
if (class_exists($classNameWithoutSuffix)) { | ||
continue; | ||
} | ||
|
||
if ($coversMatches[0] === []) { | ||
$testCaseContext::fail( | ||
sprintf( | ||
'Test "%s" is in the wrong namespace, ' . | ||
'has name different from tested class or is missing @covers annotation', | ||
$classReflection->getName() | ||
) | ||
); | ||
} | ||
|
||
/** @psalm-var list<class-string> $coveredClass */ | ||
$coveredClasses = $coversMatches['coveredClass']; | ||
if (count($coveredClasses) > 1) { | ||
continue; | ||
} | ||
|
||
$coveredClass = $coveredClasses[0]; | ||
if (class_exists($coveredClass)) { | ||
continue; | ||
} | ||
|
||
$testCaseContext::fail( | ||
sprintf( | ||
'Test %s is pointing to an non-existing class "%s"', | ||
$classReflection->getName(), | ||
$coveredClass | ||
) | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
77 changes: 77 additions & 0 deletions
77
tests/TestCheck/EveryTestHasSameNamespaceAsCoveredClassTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Cdn77\TestUtils\Tests\TestCheck; | ||
|
||
use Cdn77\TestUtils\TestCheck\EveryTestHasSameNamespaceAsCoveredClass; | ||
use Cdn77\TestUtils\Tests\BaseTestCase; | ||
use Generator; | ||
use PHPUnit\Framework\AssertionFailedError; | ||
|
||
final class EveryTestHasSameNamespaceAsCoveredClassTest extends BaseTestCase | ||
{ | ||
/** @dataProvider providerSuccess */ | ||
public function testSuccess(string $filePath): void | ||
{ | ||
$check = new EveryTestHasSameNamespaceAsCoveredClass( | ||
[__DIR__ . '/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/' . $filePath], | ||
'Tests' | ||
); | ||
$check->run($this); | ||
} | ||
|
||
/** @return Generator<array-key, list<string>> */ | ||
public function providerSuccess(): Generator | ||
{ | ||
$files = [ | ||
'IgnoreMultipleCoversTest.php', | ||
'SameNamespaceTest.php', | ||
'SameNamespaceAsLinkedCoveredClassTest.php', | ||
'CoveredClassWithSomeWhitespaceTest.php', | ||
'CoversNothingTest.php', | ||
'CoversDefaultClassTest.php', | ||
]; | ||
|
||
foreach ($files as $file) { | ||
yield $file => [$file]; | ||
} | ||
} | ||
|
||
/** @dataProvider providerFail */ | ||
public function testFail(string $filePath, string $error): void | ||
{ | ||
$this->expectException(AssertionFailedError::class); | ||
$this->expectExceptionMessage($error); | ||
|
||
$check = new EveryTestHasSameNamespaceAsCoveredClass( | ||
[__DIR__ . '/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/' . $filePath], | ||
'Tests' | ||
); | ||
$check->run($this); | ||
} | ||
|
||
/** @return Generator<array-key, list<string>> */ | ||
public function providerFail(): Generator | ||
{ | ||
yield [ | ||
'CoversNonexistentClassTest.php', | ||
'is pointing to an non-existing class', | ||
]; | ||
|
||
yield [ | ||
'CoversAndCoversNothingTest.php', | ||
'contains both @covers and @coversNothing annotations', | ||
]; | ||
|
||
yield [ | ||
'SubNamespace/SameNamespaceTest.php', | ||
'is in the wrong namespace', | ||
]; | ||
|
||
yield [ | ||
'SameNamespaceWrongNameTest.php', | ||
'is in the wrong namespace', | ||
]; | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
tests/TestCheck/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/SameNamespace.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass; | ||
|
||
final class SameNamespace | ||
{ | ||
} |
10 changes: 10 additions & 0 deletions
10
...ures/EveryTestHasSameNamespaceAsCoveredClass/tests/CoveredClassWithSomeWhitespaceTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass; | ||
|
||
/** @covers Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass\SameNamespace */ | ||
final class CoveredClassWithSomeWhitespaceTest | ||
{ | ||
} |
13 changes: 13 additions & 0 deletions
13
...eck/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/CoversAndCoversNothingTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass; | ||
|
||
/** | ||
* @coversNothing | ||
* @covers \stdClass | ||
*/ | ||
final class CoversAndCoversNothingTest | ||
{ | ||
} |
11 changes: 11 additions & 0 deletions
11
...stCheck/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/CoversDefaultClassTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass; | ||
|
||
// phpcs:ignore SlevomatCodingStandard.Files.LineLength.LineTooLong | ||
/** @coversDefaultClass Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass\SameNamespace */ | ||
final class CoversDefaultClassTest | ||
{ | ||
} |
10 changes: 10 additions & 0 deletions
10
...eck/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/CoversNonexistentClassTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass; | ||
|
||
/** @covers Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsTestedClass\Noexists */ | ||
final class CoversNonexistentClassTest | ||
{ | ||
} |
10 changes: 10 additions & 0 deletions
10
tests/TestCheck/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/CoversNothingTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass; | ||
|
||
/** @coversNothing */ | ||
final class CoversNothingTest | ||
{ | ||
} |
13 changes: 13 additions & 0 deletions
13
...Check/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/IgnoreMultipleCoversTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass; | ||
|
||
/** | ||
* @covers Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsTestedClass\A | ||
* @covers Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsTestedClass\B | ||
*/ | ||
final class IgnoreMultipleCoversTest | ||
{ | ||
} |
10 changes: 10 additions & 0 deletions
10
...s/EveryTestHasSameNamespaceAsCoveredClass/tests/SameNamespaceAsLinkedCoveredClassTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass; | ||
|
||
/** @covers Cdn77\TestUtils\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass\SameNamespace */ | ||
final class SameNamespaceAsLinkedCoveredClassTest | ||
{ | ||
} |
9 changes: 9 additions & 0 deletions
9
tests/TestCheck/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/SameNamespaceTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass; | ||
|
||
final class SameNamespaceTest | ||
{ | ||
} |
9 changes: 9 additions & 0 deletions
9
...eck/Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/SameNamespaceWrongNameTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass; | ||
|
||
final class SameNamespaceWrongNameTest | ||
{ | ||
} |
9 changes: 9 additions & 0 deletions
9
...Fixtures/EveryTestHasSameNamespaceAsCoveredClass/tests/SubNamespace/SameNamespaceTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Cdn77\TestUtils\Tests\Tests\TestCheck\Fixtures\EveryTestHasSameNamespaceAsCoveredClass\SubNamespace; | ||
|
||
final class SameNamespaceTest | ||
{ | ||
} |