📖

PHPUnit11対応でPHP-CS-Fixerを使ってのAnnotationからAttributeに置換

2024/08/19に公開

PHPUnit11でアトリビュート推奨で、アノテーションが使えなくなる件

こんな記事がある

https://qiita.com/kazumacchi/items/eb6a3059f730a9e6e3d6

休日に何気なく自分のリポジトリの PHPUnit を 11 にバージョンアップしてみたら全てのテストが動作しなくなり、調べてみたら PHPUnit 11 では PHPDoc のアノテーションは非推奨で、次のバージョンでは利用できなくなるのでアトリビュート (Attribute) を使うことが推奨されている模様。

(;´・ω・) え?マジ?

調べてみると Breaking Change みたいに大々的に表現しているページなどなく、

PHPUnit10でPHP8のAttributeが使えるようにしといたわ。
PHPUnit11でAnnotation非推奨にするわ。
PHPUnit12でAnnotation完全に使えなくするわ。

と書いてあるだけ。

https://phpunit.de/announcements/phpunit-11.html

Metadata
PHPUnit 10 introduced support for PHP 8 attributes to add metadata to test classes and test methods. Previously, annotations in special PHP comments called "docblocks" or "doc-comments" were the only way to add metadata to units of code.
In PHPUnit 11, the annotations that can be used in special PHP comments to add metadata to test classes and test methods are deprecated. Support for these annotations will be removed in PHPUnit 12.
PHPUnit 10 では、PHP 8 の属性をサポートしてテストクラスやテストメソッドにメタデータを追加できるようになりました。これまでは、PHP の特別なコメント "docblocks" や "doc-comments" にアノテーションを書くことで、コードの単位にメタデータを追加していました。
PHPUnit 11 では、PHP の特別なコメントでテストクラスやテストメソッドにメタデータを追加するためのアノテーションは非推奨となります。これらのアノテーションは、PHPUnit 12 ではサポートされなくなります。

('ω') いや気が付かんって。

もしかして: 全部手動で手直しですか?

なんか方法はないものかと検索してみたが
英語圏も含めてこれに関する記事はほぼない。

考え方を変えて、
PHPCSみたいなツールで何とかならないかと模索したところ、
PHP-CS-Fixerであればいけそうだ。

https://cs.symfony.com/doc/rules/php_unit/php_unit_attributes.html

Rule php_unit_attributes
PHPUnit attributes must be used over their respective PHPDoc-based annotations.(PHPUnit 属性は、それぞれの PHPDoc ベースのアノテーションよりも優先して使用しなければなりません。)

これをうまく使って一斉置換する方向で対応したい

ヾ(・ω<)ノ" 三三三● ⅱⅲ コロコロ♪

------------------- ↓ 本題はここから ↓-------------------

php-cs-fixer のインストール

既存コードを PHP Coding Standard 対応する目的で作成されたツール
Simfony向けて作られていたが、
長い年月を経ていろんな状況に対応するようになった

すでに使っているのであればそのまま利用で可
新規で使う場合だが、
既存しシステムに組み込むならcomposer.jsonに、
組み込まないならdocker越しかpharファイルを使うのがいい

composer install
composer require --dev friendsofphp/php-cs-fixer
phar
curl -L https://cs.symfony.com/download/php-cs-fixer-v3.phar -o php-cs-fixer
chmod a+x php-cs-fixer
docker
docker run -it --rm -v $(pwd):/code ghcr.io/php-cs-fixer/php-cs-fixer:${FIXER_VERSION:-3-php8.3} fix src

Laravel pintを使ってる場合は、
設定を追加するだけでいい。
(Laravel pintはphp-cs-fixerの拡張)

全テスト置換

事前テスト実行

まずは現状のユニットテストが全て通ることを確認

./vendor/bin/phpunit --testdox
> phpunit --testdox
PHPUnit 10.x.x by Sebastian Bergmann and contributors.

Runtime:       PHP 8.x.x
Configuration: /var/www/phpunit.xml

...............................................................  63 / 198 ( 31%)

OK, but some tests were skipped!
Tests: 50, Assertions: 100, Skipped: 0.

AnnotationからAttributeへ一斉置換

テストディレクトリを ./tests とすると

./php-cs-fixer check --rules='php_unit_attributes' ./tests # 該当ファイルのチェック
./php-cs-fixer fix --rules='php_unit_attributes' ./tests # 修正実行

再度テスト実行

結果に変化がなければ完了

./vendor/bin/phpunit --testdox
> phpunit --testdox
PHPUnit 10.x.x by Sebastian Bergmann and contributors.

Runtime:       PHP 8.x.x
Configuration: /var/www/phpunit.xml

...............................................................  63 / 198 ( 31%)

OK, but some tests were skipped!
Tests: 50, Assertions: 100, Skipped: 0.

(゚∀゚) やったか!?

差分確認

test diff
/**
- * @test
 * @testdox Test toArray method with different parameters
- * @dataProvider toArrayDifferentParameters
 */
+  #[\PHPUnit\Framework\Attributes\Test]
+  #[\PHPUnit\Framework\Attributes\DataProvider('toArrayDifferentParameters')]

@test とか @dataProvider がattributeに置換されているのがわかる。
ただ、全てのannotationに対応しているのではないようで、
@testdox は特に変更がない。

(´・ω・`) なんでや

------------------- ↓ 後書はここから ↓-------------------

その他の置換事項

PHPUnit10になってdataProviderがstatic必須になった
ついでに変更するならばruleに php_unit_data_provider_static を追加する

./php-cs-fixer fix --rules='php_unit_attributes, php_unit_data_provider_static' ./tests

もっと古いテストコードをPHPUnit10に対応する

本稿はPHPUnit11対応ではあるが、
この対応の前に古いコードはPHPUnit10対応しておく方がいい
過去のコードを細心のものにするMigrationルールがあるので、
それのPHPUnit10版である PHPUnit100Migration:risky をかけておく

./php-cs-fixer fix --rules=@PHPUnit100Migration:risky --allow-risky=yes ./tests

Discussion