Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support PHPUnit v9.1 naming for some asserts #7997

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion doc/ruleSets/PHPUnit100MigrationRisky.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Using this rule set may lead to changes in your code's logic and behaviour. Use
Rules
-----

- `@PHPUnit84Migration:risky <./PHPUnit84MigrationRisky.rst>`_
- `@PHPUnit91Migration:risky <./PHPUnit91MigrationRisky.rst>`_
- `php_unit_data_provider_static <./../rules/php_unit/php_unit_data_provider_static.rst>`_ with config:

``['force' => true]``
Expand Down
22 changes: 22 additions & 0 deletions doc/ruleSets/PHPUnit91MigrationRisky.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
======================================
Rule set ``@PHPUnit91Migration:risky``
======================================

Rules to improve tests code for PHPUnit 9.1 compatibility.

Warning
-------

This set contains rules that are risky
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Using this rule set may lead to changes in your code's logic and behaviour. Use it with caution and review changes before incorporating them into your code base.

Rules
-----

- `@PHPUnit84Migration:risky <./PHPUnit84MigrationRisky.rst>`_
- `php_unit_dedicate_assert <./../rules/php_unit/php_unit_dedicate_assert.rst>`_ with config:

``['target' => '9.1']``

1 change: 1 addition & 0 deletions doc/ruleSets/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ List of Available Rule sets
- `@PHPUnit60Migration:risky <./PHPUnit60MigrationRisky.rst>`_
- `@PHPUnit75Migration:risky <./PHPUnit75MigrationRisky.rst>`_
- `@PHPUnit84Migration:risky <./PHPUnit84MigrationRisky.rst>`_
- `@PHPUnit91Migration:risky <./PHPUnit91MigrationRisky.rst>`_
- `@PHPUnit100Migration:risky <./PHPUnit100MigrationRisky.rst>`_
- `@PSR1 <./PSR1.rst>`_
- `@PSR2 <./PSR2.rst>`_
Expand Down
8 changes: 6 additions & 2 deletions doc/rules/php_unit/php_unit_dedicate_assert.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Configuration

Target version of PHPUnit.

Allowed values: ``'3.0'``, ``'3.5'``, ``'5.0'``, ``'5.6'`` and ``'newest'``
Allowed values: ``'3.0'``, ``'3.5'``, ``'5.0'``, ``'5.6'``, ``'9.1'`` and ``'newest'``

Default value: ``'newest'``

Expand Down Expand Up @@ -133,9 +133,13 @@ The rule is part of the following rule sets:

``['target' => '5.6']``

- `@PHPUnit91Migration:risky <./../../ruleSets/PHPUnit91MigrationRisky.rst>`_ with config:

``['target' => '9.1']``

- `@PHPUnit100Migration:risky <./../../ruleSets/PHPUnit100MigrationRisky.rst>`_ with config:

``['target' => '5.6']``
``['target' => '9.1']``


References
Expand Down
4 changes: 4 additions & 0 deletions doc/rules/php_unit/php_unit_dedicate_assert_internal_type.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ The rule is part of the following rule sets:

``['target' => '7.5']``

- `@PHPUnit91Migration:risky <./../../ruleSets/PHPUnit91MigrationRisky.rst>`_ with config:

``['target' => '7.5']``

- `@PHPUnit100Migration:risky <./../../ruleSets/PHPUnit100MigrationRisky.rst>`_ with config:

``['target' => '7.5']``
Expand Down
4 changes: 4 additions & 0 deletions doc/rules/php_unit/php_unit_expectation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ The rule is part of the following rule sets:

``['target' => '8.4']``

- `@PHPUnit91Migration:risky <./../../ruleSets/PHPUnit91MigrationRisky.rst>`_ with config:

``['target' => '8.4']``

- `@PHPUnit100Migration:risky <./../../ruleSets/PHPUnit100MigrationRisky.rst>`_ with config:

``['target' => '8.4']``
Expand Down
4 changes: 4 additions & 0 deletions doc/rules/php_unit/php_unit_mock.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ The rule is part of the following rule sets:

``['target' => '5.5']``

- `@PHPUnit91Migration:risky <./../../ruleSets/PHPUnit91MigrationRisky.rst>`_ with config:

``['target' => '5.5']``

- `@PHPUnit100Migration:risky <./../../ruleSets/PHPUnit100MigrationRisky.rst>`_ with config:

``['target' => '5.5']``
Expand Down
4 changes: 4 additions & 0 deletions doc/rules/php_unit/php_unit_namespaced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ The rule is part of the following rule sets:

``['target' => '6.0']``

- `@PHPUnit91Migration:risky <./../../ruleSets/PHPUnit91MigrationRisky.rst>`_ with config:

``['target' => '6.0']``

- `@PHPUnit100Migration:risky <./../../ruleSets/PHPUnit100MigrationRisky.rst>`_ with config:

``['target' => '6.0']``
Expand Down
4 changes: 4 additions & 0 deletions doc/rules/php_unit/php_unit_no_expectation_annotation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ The rule is part of the following rule sets:

``['target' => '4.3']``

- `@PHPUnit91Migration:risky <./../../ruleSets/PHPUnit91MigrationRisky.rst>`_ with config:

``['target' => '4.3']``

- `@PHPUnit100Migration:risky <./../../ruleSets/PHPUnit100MigrationRisky.rst>`_ with config:

``['target' => '4.3']``
Expand Down
144 changes: 131 additions & 13 deletions src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,77 @@
final class PhpUnitDedicateAssertFixer extends AbstractPhpUnitFixer implements ConfigurableFixerInterface
{
/**
* @var array<string, array{positive: string, negative: false|string, argument_count?: int, swap_arguments?: true}|true>
* @var array{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to have this change reverted.
it's giving extra knowledge of "method X will / will not have those keys", while in fact we do not rely on it anywhere - we rely on contract that is "any method, if configured into array, will have those key obligatory and those keys optional" - for whole algo it doesn't matter which method will have which configuration.

then, you also changed configuration from swap_arguments: true to swap_arguments: bool, which is extending the type (claiming it can take false as value, which is not supported). same for changes for negative

* array_key_exists: array{
* positive: string,
* negative: string,
* argument_count: int
* },
* empty: array{
* positive: string,
* negative: string
* },
* file_exists: array{
* positive: string,
* negative: string
* },
* is_array: bool,
* is_bool: bool,
* is_callable: bool,
* is_dir: array{
* positive: string,
* negative: string
* },
* is_double: bool,
* is_float: bool,
* is_infinite: array{
* positive: string,
* negative: string
* },
* is_int: bool,
* is_integer: bool,
* is_long: bool,
* is_nan: array{
* positive: string,
* negative: bool
* },
* is_null: array{
* positive: string,
* negative: string
* },
* is_numeric: bool,
* is_object: bool,
* is_readable: array{
* positive: string,
* negative: string
* },
* is_real: bool,
* is_resource: bool,
* is_scalar: bool,
* is_string: bool,
* is_writable: array{
* positive: string,
* negative: string
* },
* str_contains: array{
* positive: string,
* negative: string,
* argument_count: int,
* swap_arguments: bool
* },
* str_ends_with: array{
* positive: string,
* negative: string,
* argument_count: int,
* swap_arguments: bool
* },
* str_starts_with: array{
* positive: string,
* negative: string,
* argument_count: int,
* swap_arguments: bool
* }
* }
*/
private static array $fixMap = [
'array_key_exists' => [
Expand Down Expand Up @@ -106,6 +176,7 @@
'argument_count' => 2,
'swap_arguments' => true,
],
'assertNotIsReadable' => true,
];

/**
Expand Down Expand Up @@ -169,6 +240,15 @@
'str_contains',
]);
}

if (PhpUnitTargetVersion::fulfills($this->configuration['target'], PhpUnitTargetVersion::VERSION_9_1)) {
$this->functions = array_merge($this->functions, [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

those are not native, global functions but methods of PHPUnit. please don't mix content of ->functions.

'assertdirectorynotexists',
'assertnotisreadable',
'assertnotiswritable',
'assertfilenotexists',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more are missing, eg assertFileNotIsReadable
ref https://github.com/sebastianbergmann/phpunit/blob/9.1.5/ChangeLog-9.1.md

]);
}
}

public function isRisky(): bool
Expand Down Expand Up @@ -230,23 +310,24 @@

foreach ($this->getPreviousAssertCall($tokens, $startIndex, $endIndex) as $assertCall) {
// test and fix for assertTrue/False to dedicated asserts
if ('asserttrue' === $assertCall['loweredName'] || 'assertfalse' === $assertCall['loweredName']) {
if (\in_array($assertCall['loweredName'], ['asserttrue', 'assertfalse'], true)) {
$this->fixAssertTrueFalse($tokens, $argumentsAnalyzer, $assertCall);

continue;
}

if (
'assertsame' === $assertCall['loweredName']
|| 'assertnotsame' === $assertCall['loweredName']
|| 'assertequals' === $assertCall['loweredName']
|| 'assertnotequals' === $assertCall['loweredName']
) {
if (\in_array(
$assertCall['loweredName'],
['assertsame', 'assertnotsame', 'assertequals', 'assertnotequals'],
true
)) {
$this->fixAssertSameEquals($tokens, $assertCall);

continue;
}
}

foreach ($this->getPreviousAssertCall($tokens, $startIndex, $endIndex) as $assertCall) {
$this->fixAssertNewNames($tokens, $assertCall);
}
}

protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
Expand All @@ -259,6 +340,7 @@
PhpUnitTargetVersion::VERSION_3_5,
PhpUnitTargetVersion::VERSION_5_0,
PhpUnitTargetVersion::VERSION_5_6,
PhpUnitTargetVersion::VERSION_9_1,
PhpUnitTargetVersion::VERSION_NEWEST,
])
->setDefault(PhpUnitTargetVersion::VERSION_NEWEST)
Expand Down Expand Up @@ -323,11 +405,12 @@

$isPositive = $isPositive ? 'positive' : 'negative';

if (false === self::$fixMap[$content][$isPositive]) {
$replace = self::$fixMap[$content][$isPositive];
if (false === $replace) {
return;
}

$tokens[$assertCall['index']] = new Token([T_STRING, self::$fixMap[$content][$isPositive]]);
$tokens[$assertCall['index']] = new Token([T_STRING, (string) $replace]);

Check warning on line 413 in src/Fixer/PhpUnit/PhpUnitDedicateAssertFixer.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 mutation tests

Escaped Mutant for Mutator "CastString": --- Original +++ New @@ @@ if (false === $replace) { return; } - $tokens[$assertCall['index']] = new Token([T_STRING, (string) $replace]); + $tokens[$assertCall['index']] = new Token([T_STRING, $replace]); $this->removeFunctionCall($tokens, $testDefaultNamespaceTokenIndex, $testIndex, $testOpenIndex, $testCloseIndex); if (self::$fixMap[$content]['swap_arguments'] ?? false) { if (2 !== $expectedCount) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$this->removeFunctionCall($tokens, $testDefaultNamespaceTokenIndex, $testIndex, $testOpenIndex, $testCloseIndex);

if (self::$fixMap[$content]['swap_arguments'] ?? false) {
Expand Down Expand Up @@ -484,7 +567,7 @@

$lowerContent = strtolower($tokens[$countCallIndex]->getContent());

if ('count' !== $lowerContent && 'sizeof' !== $lowerContent) {
if (!\in_array($lowerContent, ['count', 'sizeof'], true)) {
return; // not a call to "count" or "sizeOf"
}

Expand Down Expand Up @@ -625,4 +708,39 @@

return $clone;
}

/**
* @param array{
* index: int,
* loweredName: string,
* openBraceIndex: int,
* closeBraceIndex: int,
* } $assertCall
*/
private function fixAssertNewNames(Tokens $tokens, array $assertCall): void
{
if (!\in_array($assertCall['loweredName'], $this->functions, true)) {
return;
}

$replacement = null;
if ('assertnotisreadable' === $assertCall['loweredName']) {
$replacement = 'assertIsNotReadable';
} elseif ('assertnotiswritable' === $assertCall['loweredName']) {
$replacement = 'assertIsNotWritable';
} elseif ('assertdirectorynotexists' === $assertCall['loweredName']) {
$replacement = 'assertDirectoryDoesNotExist';
} elseif ('assertfilenotexists' === $assertCall['loweredName']) {
$replacement = 'assertFileDoesNotExist';
}
Comment on lines +727 to +735

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange that mess-detector prefers this over switch statement, not everything can be refactored to polymorphism, especially string comparison.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it complains because switch-case uses == and not ===. It is a good it's complaining.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

        $replacements = [
            'assertnotisreadable' => 'assertIsNotReadable',
            'assertnotiswritable' => 'assertIsNotWritable',
            'assertdirectorynotexists' => 'assertDirectoryDoesNotExist',
            'assertfilenotexists' => 'assertFileDoesNotExist',
        ];
        $replacement = $replacements[$assertCall['loweredName']] ?? null;

(we can't use match yet)


if (null === $replacement) {
return;
}

$tokens[$assertCall['index']] = new Token([
T_STRING,
$replacement,
]);
}
}
1 change: 1 addition & 0 deletions src/Fixer/PhpUnit/PhpUnitTargetVersion.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ final class PhpUnitTargetVersion
public const VERSION_6_0 = '6.0';
public const VERSION_7_5 = '7.5';
public const VERSION_8_4 = '8.4';
public const VERSION_9_1 = '9.1';
public const VERSION_NEWEST = 'newest';

private function __construct() {}
Expand Down
2 changes: 1 addition & 1 deletion src/RuleSet/Sets/PHPUnit100MigrationRiskySet.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
{
public function getRules(): array
{
return [

Check warning on line 26 in src/RuleSet/Sets/PHPUnit100MigrationRiskySet.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 mutation tests

Escaped Mutant for Mutator "ArrayItemRemoval": --- Original +++ New @@ @@ { public function getRules() : array { - return ['@PHPUnit91Migration:risky' => true, 'php_unit_data_provider_static' => ['force' => true]]; + return ['php_unit_data_provider_static' => ['force' => true]]; } }
'@PHPUnit84Migration:risky' => true,
'@PHPUnit91Migration:risky' => true,

Check warning on line 27 in src/RuleSet/Sets/PHPUnit100MigrationRiskySet.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 mutation tests

Escaped Mutant for Mutator "TrueValue": --- Original +++ New @@ @@ { public function getRules() : array { - return ['@PHPUnit91Migration:risky' => true, 'php_unit_data_provider_static' => ['force' => true]]; + return ['@PHPUnit91Migration:risky' => false, 'php_unit_data_provider_static' => ['force' => true]]; } }
'php_unit_data_provider_static' => ['force' => true],
];
}
Expand Down
34 changes: 34 additions & 0 deletions src/RuleSet/Sets/PHPUnit91MigrationRiskySet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <[email protected]>
* Dariusz Rumiński <[email protected]>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace PhpCsFixer\RuleSet\Sets;

use PhpCsFixer\Fixer\PhpUnit\PhpUnitTargetVersion;
use PhpCsFixer\RuleSet\AbstractMigrationSetDescription;

/**
* @internal
*/
final class PHPUnit91MigrationRiskySet extends AbstractMigrationSetDescription
{
public function getRules(): array
{
return [

Check warning on line 27 in src/RuleSet/Sets/PHPUnit91MigrationRiskySet.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 mutation tests

Escaped Mutant for Mutator "ArrayItemRemoval": --- Original +++ New @@ @@ { public function getRules() : array { - return ['@PHPUnit84Migration:risky' => true, 'php_unit_dedicate_assert' => ['target' => PhpUnitTargetVersion::VERSION_9_1]]; + return ['php_unit_dedicate_assert' => ['target' => PhpUnitTargetVersion::VERSION_9_1]]; } }
'@PHPUnit84Migration:risky' => true,

Check warning on line 28 in src/RuleSet/Sets/PHPUnit91MigrationRiskySet.php

View workflow job for this annotation

GitHub Actions / PHP 8.3 mutation tests

Escaped Mutant for Mutator "TrueValue": --- Original +++ New @@ @@ { public function getRules() : array { - return ['@PHPUnit84Migration:risky' => true, 'php_unit_dedicate_assert' => ['target' => PhpUnitTargetVersion::VERSION_9_1]]; + return ['@PHPUnit84Migration:risky' => false, 'php_unit_dedicate_assert' => ['target' => PhpUnitTargetVersion::VERSION_9_1]]; } }
'php_unit_dedicate_assert' => [
'target' => PhpUnitTargetVersion::VERSION_9_1,
],
];
}
}