Skip to content

Commit

Permalink
Enhancement: Implement Classes\PHPUnit\Framework\TestCaseWithSuffixRule
Browse files Browse the repository at this point in the history
  • Loading branch information
localheinz committed May 10, 2020
1 parent cebf79a commit bdccf23
Show file tree
Hide file tree
Showing 14 changed files with 320 additions and 3 deletions.
1 change: 1 addition & 0 deletions .php_cs.fixture
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ $config = Config\Factory::fromRuleSet(new Config\RuleSet\Php71(''), [
'declare_strict_types' => false,
'error_suppression' => false,
'final_class' => false,
'final_internal_class' => false,
'final_public_method_for_abstract_class' => false,
'header_comment' => false,
'lowercase_constants' => false,
Expand Down
15 changes: 13 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## Unreleased

For a full diff see [`0.14.4...master`][0.14.4...master].
For a full diff see [`0.15.0...master`][0.15.0...master].

## [`0.15.0`][0.15.0]

For a full diff see [`0.14.4...0.15.0`][0.14.4...0.15.0].

### Added

* Added `Classes\PHPUnit\Framework\TestCaseWithSuffixRule`, which reports an error when a concrete class extending `PHPUnit\Framework\TestCase` does not have a `Test` suffix ([#225], by [@localheinz]

## [`0.14.4`][0.14.4]

Expand Down Expand Up @@ -314,6 +322,7 @@ For a full diff see [`362c7ea...0.1.0`][362c7ea...0.1.0].
[0.14.2]: https://github.com/ergebnis/phpstan-rules/releases/tag/0.14.2
[0.14.3]: https://github.com/ergebnis/phpstan-rules/releases/tag/0.14.3
[0.14.4]: https://github.com/ergebnis/phpstan-rules/releases/tag/0.14.4
[0.15.0]: https://github.com/ergebnis/phpstan-rules/releases/tag/0.15.0

[362c7ea...0.1.0]: https://github.com/ergebnis/phpstan-rules/compare/362c7ea...0.1.0
[0.1.0...0.2.0]: https://github.com/ergebnis/phpstan-rules/compare/0.1.0...0.2.0
Expand All @@ -338,7 +347,8 @@ For a full diff see [`362c7ea...0.1.0`][362c7ea...0.1.0].
[0.14.1...0.14.2]: https://github.com/ergebnis/phpstan-rules/compare/0.14.1...0.14.2
[0.14.2...0.14.3]: https://github.com/ergebnis/phpstan-rules/compare/0.14.2...0.14.3
[0.14.3...0.14.4]: https://github.com/ergebnis/phpstan-rules/compare/0.14.3...0.14.4
[0.14.4...master]: https://github.com/ergebnis/phpstan-rules/compare/0.14.4...master
[0.14.4...0.15.0]: https://github.com/ergebnis/phpstan-rules/compare/0.14.4...0.15.0
[0.15.0...master]: https://github.com/ergebnis/phpstan-rules/compare/0.15.0...master

[#1]: https://github.com/ergebnis/phpstan-rules/pull/1
[#4]: https://github.com/ergebnis/phpstan-rules/pull/4
Expand Down Expand Up @@ -387,6 +397,7 @@ For a full diff see [`362c7ea...0.1.0`][362c7ea...0.1.0].
[#166]: https://github.com/ergebnis/phpstan-rules/pull/166
[#186]: https://github.com/ergebnis/phpstan-rules/pull/186
[#202]: https://github.com/ergebnis/phpstan-rules/pull/202
[#225]: https://github.com/ergebnis/phpstan-rules/pull/225

[@ergebnis]: https://github.com/ergebnis
[@Great-Antique]: https://github.com/Great-Antique
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ This package provides the following rules for use with [`phpstan/phpstan`](https

* [`Ergebnis\PHPStan\Rules\Classes\FinalRule`](https://github.com/ergebnis/phpstan-rules#classesfinalrule)
* [`Ergebnis\PHPStan\Rules\Classes\NoExtendsRule`](https://github.com/ergebnis/phpstan-rules#classesnoextendsrule)
* [`Ergebnis\PHPStan\Rules\Classes\PHPUnit\Framework\TestCaseWithSuffixRule`](https://github.com/ergebnis/phpstan-rules#classesphpunitframeworktestcasewithsuffixrule)
* [`Ergebnis\PHPStan\Rules\Closures\NoNullableReturnTypeDeclarationRule`](https://github.com/ergebnis/phpstan-rules#closuresnonullablereturntypedeclarationrule)
* [`Ergebnis\PHPStan\Rules\Closures\NoParameterWithNullableTypeDeclarationRule`](https://github.com/ergebnis/phpstan-rules#closuresnoparameterwithnullabletypedeclarationrule)
* [`Ergebnis\PHPStan\Rules\Closures\NoParameterWithNullDefaultValueRule`](https://github.com/ergebnis/phpstan-rules#closuresnoparameterwithnulldefaultvaluerule)
Expand Down Expand Up @@ -118,6 +119,9 @@ parameters:
- Ergebnis\PHPStan\Rules\Test\Integration\AbstractTestCase
- PHPStan\Testing\RuleTestCase
```
#### `Classes\PHPUnit\Framework\TestCaseWithSuffixRule`

This rule reports an error when a concrete class is a sub-class of `PHPUnit\Framework\TestCase` but does not have a `Test` suffix.

### Closures

Expand Down
5 changes: 5 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ parameters:
count: 1
path: src/Classes/NoExtendsRule.php

-
message: "#^Language construct isset\\(\\) should not be used\\.$#"
count: 1
path: src/Classes/PHPUnit/Framework/TestCaseWithSuffixRule.php

-
message: "#^Language construct isset\\(\\) should not be used\\.$#"
count: 1
Expand Down
11 changes: 10 additions & 1 deletion psalm-baseline.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="3.10.1@eeed5ecccc10131397f0eb7ee6da810c0be3a7fc">
<files psalm-version="3.11.2@d470903722cfcbc1cd04744c5491d3e6d13ec3d9">
<file src="src/Classes/FinalRule.php">
<MixedArgument occurrences="3">
<code>$node-&gt;namespacedName</code>
Expand All @@ -20,6 +20,15 @@
</MixedArgument>
<PropertyTypeCoercion occurrences="1"/>
</file>
<file src="src/Classes/PHPUnit/Framework/TestCaseWithSuffixRule.php">
<MixedArgument occurrences="2">
<code>$node-&gt;namespacedName-&gt;toString()</code>
<code>$node-&gt;namespacedName</code>
</MixedArgument>
<MixedMethodCall occurrences="1">
<code>toString</code>
</MixedMethodCall>
</file>
<file src="src/Functions/NoNullableReturnTypeDeclarationRule.php">
<MixedArgument occurrences="1">
<code>$node-&gt;namespacedName</code>
Expand Down
6 changes: 6 additions & 0 deletions rules.neon
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,19 @@ services:
classesNotRequiredToBeAbstractOrFinal: %ergebnis.classesNotRequiredToBeAbstractOrFinal%
tags:
- phpstan.rules.rule

-
class: Ergebnis\PHPStan\Rules\Classes\NoExtendsRule
arguments:
classesAllowedToBeExtended: %ergebnis.classesAllowedToBeExtended%
tags:
- phpstan.rules.rule

-
class: Ergebnis\PHPStan\Rules\Classes\PHPUnit\Framework\TestCaseWithSuffixRule
tags:
- phpstan.rules.rule

-
class: Ergebnis\PHPStan\Rules\Methods\NoParameterWithContainerTypeDeclarationRule
arguments:
Expand Down
99 changes: 99 additions & 0 deletions src/Classes/PHPUnit/Framework/TestCaseWithSuffixRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

declare(strict_types=1);

/**
* Copyright (c) 2018-2020 Andreas Möller
*
* For the full copyright and license information, please view
* the LICENSE.md file that was distributed with this source code.
*
* @see https://github.com/ergebnis/phpstan-rules
*/

namespace Ergebnis\PHPStan\Rules\Classes\PHPUnit\Framework;

use PhpParser\Node;
use PHPStan\Analyser;
use PHPStan\Broker;
use PHPStan\Rules;
use PHPStan\ShouldNotHappenException;

final class TestCaseWithSuffixRule implements Rules\Rule
{
/**
* @var string[]
*/
private static $phpunitTestCaseClassNames = [
'PHPUnit\Framework\TestCase',
];

/**
* @var Broker\Broker
*/
private $broker;

public function __construct(Broker\Broker $broker)
{
$this->broker = $broker;
}

public function getNodeType(): string
{
return Node\Stmt\Class_::class;
}

public function processNode(Node $node, Analyser\Scope $scope): array
{
if (!$node instanceof Node\Stmt\Class_) {
throw new ShouldNotHappenException(\sprintf(
'Expected node to be instance of "%s", but got instance of "%s" instead.',
Node\Stmt\Class_::class,
\get_class($node)
));
}

if ($node->isAbstract()) {
return [];
}

if (!$node->extends instanceof Node\Name) {
return [];
}

if (!isset($node->namespacedName)) {
return [];
}

/** @var string $fullyQualifiedClassName */
$fullyQualifiedClassName = $node->namespacedName->toString();

$classReflection = $this->broker->getClass($fullyQualifiedClassName);

$extendedPhpunitTestCaseClassName = '';

foreach (self::$phpunitTestCaseClassNames as $phpunitTestCaseClassName) {
if ($classReflection->isSubclassOf($phpunitTestCaseClassName)) {
$extendedPhpunitTestCaseClassName = $phpunitTestCaseClassName;

break;
}
}

if ('' === $extendedPhpunitTestCaseClassName) {
return [];
}

if (1 === \preg_match('/Test$/', $fullyQualifiedClassName)) {
return [];
}

return [
\sprintf(
'Class %s extends %s, is concrete, but does not have a Test suffix.',
$fullyQualifiedClassName,
$extendedPhpunitTestCaseClassName
),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Ergebnis\PHPStan\Rules\Test\Fixture\Classes\PHPUnit\Framework\TestCaseWithSuffixRule\Failure;

use PHPUnit\Framework;

/**
* @internal
*/
abstract class AbstractTestCase extends Framework\TestCase
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Ergebnis\PHPStan\Rules\Test\Fixture\Classes\PHPUnit\Framework\TestCaseWithSuffixRule\Failure;

/**
* @internal
*
* @coversNothing
*/
final class ConcreteTestCaseExtendingAbstractTestCaseWithoutTestSuffix extends AbstractTestCase
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Ergebnis\PHPStan\Rules\Test\Fixture\Classes\PHPUnit\Framework\TestCaseWithSuffixRule\Failure;

use PHPUnit\Framework;

/**
* @internal
*
* @coversNothing
*/
final class ConcreteTestCaseWithoutTestSuffix extends Framework\TestCase
{
public function testFooIsNotBar(): void
{
self::assertNotSame('bar', 'foo');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Ergebnis\PHPStan\Rules\Test\Fixture\Classes\PHPUnit\Framework\TestCaseWithSuffixRule\Success;

use PHPUnit\Framework;

/**
* @internal
*
* @coversNothing
*/
final class ConcreteTestCaseWithSuffixTest extends Framework\TestCase
{
public function testFooIsNotBar(): void
{
self::assertNotSame('bar', 'foo');
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Ergebnis\PHPStan\Rules\Test\Fixture\Classes\PHPUnit\Framework\TestCaseWithSuffixRule\Success;

use PHPUnit\Framework;

/**
* @internal
*/
abstract class ExplicitlyAbstractTestCase extends Framework\TestCase
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Ergebnis\PHPStan\Rules\Test\Fixture\Classes\PHPUnit\Framework\TestCaseWithSuffixRule\Success;

use PHPUnit\Framework;

/**
* @internal
*
* @coversNothing
*/
class ImplicitlyAbstractTestCase extends Framework\TestCase
{
abstract protected function foo();
}
Loading

0 comments on commit bdccf23

Please sign in to comment.