PHPUnit 11 でアノテーションからアトリビュート (Attribute) に移行するメモ

2024年02月に [PHPUnit11](https://phpunit.de/announcements/phpunit-11.html) がリリースされました。

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

```bash
Metadata found in doc-comment for method Tests\XxxxTest::xxxxxx(). 
Metadata in doc-comments is deprecated and will no longer be supported in PHPUnit 12. 
Update your test code to use attributes instead.
```

多分非推奨を無視するオプションとかがあるんでしょうけど、どうせ次のバージョンでアノテーションが使えなくなるのであれば PHPUnit11 のうちに アトリビュートを学んでおこうかと、よく使いそうなアトリビュートをメモ。

## test アノテーション → Test アトリビュート

テストメソッドであることを指定する

:::note info
メソッド名の先頭に test を入れることで代替できる
その場合、アノテーションもアトリビュートも書く必要はない
:::

:::note warn
僕はテストメソッド名を日本語で書いているので、先頭に test って書くのが違和感あってアノテーションの方を使っていました
それが理由で PHPUnit 11 にアップデートしてテストが全部動かなくなりました
:::


### PHPUnit 11 から非推奨
```php
/**
 * @test
 */
public function レンタカーの予約である()
{
    // 略
}
```

### PHPUnit 12 から

```php
use PHPUnit\Framework\Attributes\Test;

// 略

#[Test]
public function レンタカーの予約である()
{
    // 略
}
 ```

## depends アノテーション → Depends アトリビュート

### PHPUnit 11 から非推奨

```php
/**
 * @test
 */
public function ホテルの予約である()
{
   // 略
}

/**
 * @test
 * @depends ホテルの予約である
 */
public function レンタカーの予約である()
{
   // 略
}
```

### PHPUnit 12 から

```php
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\Depends;

// 略

#[Test]
public function ホテルの予約である()
{
   // 略
}

#[Test]
#[Depends('ホテルの予約である')]
public function レンタカーの予約である()
{
   // 略
}
```

## dataProvider アノテーション → DataProvider アトリビュート

### PHPUnit 11 から非推奨

```php
/**
 * @test
 * @dataProvider annotationProvider
 */
public function レンタカーの予約である(bool $result, int $value)
{
    // 略
}

/**
 * @return array
 */
public static function annotationProvider(): array
{
    // 略
}
```

### PHPUnit 12 から
```php
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\DataProvider;

// 略

#[Test]
#[DataProvider('attributeProvider')]
public function レンタカーの予約である(bool $result, int $value)
{
    // 略
}

/**
 * @return array
 */
public static function attributeProvider(): array
{
    // 略
}
```

#### または TestWith 
```php
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\TestWith;

// 略

#[Test]
#[TestWith([false, 0])]
#[TestWith([true, 1])]
#[TestWith([true, 2])]
public function レンタカーの予約である(bool $result, int $value)
{
    // 略
}
```

#### または DataProviderExternal で外部ファイルの dataProvider を指定

```php
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\DataProviderExternal;
use Test\TestCase\DataProvider\ExternalDataProvider;

// 略

#[Test]
#[DataProviderExternal(ExternalDataProvider::class, 'attributeProvider')]
public function レンタカーの予約である(bool $result, int $value)
{
    // 略
}
```

```php
namespace Test\TestCase\DataProvider;

// 外部ファイルのクラス
class ExternalDataProvider
{
    /**
     * @return array
     */
    public static function attributeProvider(): array
    {
        // 略
    }
}
```

## group アノテーション → Group アトリビュート

### PHPUnit 11 から非推奨

```php
/**
 * @test
 * @group rentacar
 */
public function レンタカーの予約である()
{
    // 略
}
```

### PHPUnit 12 から

```php
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\Group;

// 略

#[Test]
#[Group('rentacar')]
public function レンタカーの予約である()
{
    // 略
}
```

あれ、ここまで書いて思いましたが意外と簡単ですね…
ちょっと面倒なのが、使う Attribute を use しなければならないくらいでしょうか

わざわざメモしなくてもマニュアル見ながら苦もなく移行出来そうな気がしてきました

以上

# 参考

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