Kodokon kodokon.com

品質:PHPUnit、PHPStan、そしてPSR

PHPUnitのテスト、レベル9のPHPStan静的解析、そしてPSR標準で、プロのようにコードを道具立てしましょう。

10 分 · 3 問

このレッスンを Kodokon で開く

熟練者のコードは、巧妙なトリックよりもそのセーフティネットによって見分けられます。三つの補完的な柱があります。コードを実行することで振る舞いを検証するテスト(PHPUnit)、何も実行せずに性質を証明する静的解析(PHPStan)、そしてエコシステムを相互運用可能にする共有標準(PSR)です。すべては開発用の依存関係として、Composerでインストールできます。

BASH
composer require --dev phpunit/phpunit
composer require --dev phpstan/phpstan
./vendor/bin/phpunit --testdox tests
./vendor/bin/phpstan analyse src --level=9
--testdoxオプションは、テストを読みやすい仕様として表示する

PHPUnit 10以降、メタデータはPHPアトリビュートとして書かれます。#[DataProvider]がdocblockの@dataProviderアノテーションを置き換えます。データプロバイダーはpublicかつstaticでなければなりません。PHPUnitがテストクラスをインスタンス化するよりも前に、それを読むからです。各データセットは説明的なキーを持ち、ケースが失敗したときにそのまま表示されます。accentsの失敗は即座に特定できます。

PHP
<?php
declare(strict_types=1);

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

final class SlugifierTest extends TestCase
{
    #[DataProvider('provideTitles')]
    public function testSlugify(
        string $input,
        string $expected
    ): void {
        $this->assertSame($expected, slugify($input));
    }

    public static function provideTitles(): array
    {
        return [
            'simple' => [
                'Hello World', 'hello-world'
            ],
            'accents' => [
                'Déjà vu', 'deja-vu'
            ],
        ];
    }
}
プロジェクトの別の場所で定義されたslugify関数をテストする

PHPStanは、その厳格さを0から9までのレベルで段階づけます(最近のバージョンにはレベル10があります)。レベル9では、あらゆるmixed値が、まず明示的なチェックによって絞り込まれない限り使えなくなります。その真の力は、PHPエンジンは無視するが解析ツールは検証するdocblockの型から来ます。配列の形array{email: string}、リストlist<int>、ジェネリクスです。これらは文書化すると同時に証明します。

PHP
<?php
declare(strict_types=1);

function findEmail(?array $user): string
{
    return $user['email'];
}

/**
 * @param array{email: string}|null $user
 */
function findEmailSafe(?array $user): string
{
    return $user === null
        ? 'n/a'
        : $user['email'];
}
レベル9。最初の関数は却下され(nullへのアクセスの可能性、不明なキーと型)、二番目は通る

PSR(PHP Standards Recommendations)はPHP-FIGの規約です。PSR-1PSR-12はスタイルを標準化します。インデント、波括弧、インポートの順序で、php-cs-fixerphpcsによって自動的に適用されます。PSR-4はオートローディングを定義します。名前空間の接頭辞がディレクトリに対応づけられ、これによりComposerは手作業のrequireなしに任意のクラスを見つけられます。最後に、インターフェースのPSR、ロガーのためのPSR-3、HTTPメッセージのためのPSR-7は、それを利用するコードに触れることなく、あるライブラリを別のものに差し替えることを可能にします。

理解度チェック

このレッスンの要点をしっかり覚えているか確認しましょう。

  1. PHPUnit 10以降、#[DataProvider]で参照されるデータプロバイダーのメソッドにはどんな制約が適用されますか?
    • publicかつstaticでなければならない。PHPUnitがテストクラスをインスタンス化する前にそれを読むから
    • 配列ではなく、必ずジェネレーターを返さなければならない
    • テストと同じ名前で、末尾にProviderを付けなければならない
  2. PHPStanのレベル9は何を課しますか?
    • docblockを禁止し、ネイティブな型だけにすること
    • mixedの厳格な扱い。まず絞り込まない限り、そのような値は使えない
    • 解析されたコードのテストカバレッジ100パーセント
  3. PSR-4標準は何を定義しますか?
    • アプリケーションのログメッセージの形式
    • 名前空間の接頭辞とディレクトリの間の対応づけ。Composerのオートローダーが使う
    • インデントのスタイルと波括弧の配置