0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PHPAdvent Calendar 2024

Day 22

【PHPStan】カスタムルールのユニットテストを作成する

Last updated at Posted at 2024-12-21

初めに

PHPStanでは独自のカスタムルールを作成できるということをこちらの記事で解説しました。今回は作成したカスタムルールのユニットテストを作成してみようと思います。

(前提)PHPStanはPHPUnitを用いてUnitTestを書くことができる

PHPStanではユニットテストにPHPUnitが採用されています。各ルールはRuleTestCaseというクラスを継承してテストケースが作成されており、カスタムクラスでも同様にこのクラスを継承して作成します。

以下はRuleTestCaseの一部抜粋です。(全部で見たい方はこちらからどうぞ)

RuleTestCaseクラス
/**
 * @api
 * @template TRule of Rule
 */
abstract class RuleTestCase extends PHPStanTestCase
{
	/**
	 * @return TRule
	 */
	abstract protected function getRule(): Rule;
 
    /**
	 * @param string[] $files
	 * @param list<array{0: string, 1: int, 2?: string|null}> $expectedErrors
	 */
	public function analyse(array $files, array $expectedErrors): void
	{
		// テストケースを実行する処理が書いてある
        // 見づらくなるため割愛
	}
}

ポイント

  • getRule()メソッド
    • テストしたいルールクラス指定する
  • analyse()メソッド
    • 実際に検証を行うメソッド
    • 引数で以下の情報をもらい、getRule()で指定したルールを検証する
      • 検証対象のファイルのパス
      • 期待値(出力されてほしいエラー)

UnitTest作成方法

ということで、実際に実装してみます。
今回は以下のようなカスタムルールを用意しました。このテストケースを作成してみます。

MethodNameRule
class MethodNameRule implements Rule
{
    public function getNodeType(): string
    {
        return Node\Stmt\ClassMethod::class;
    }

    /**
     * @param Node\Stmt\ClassMethod $node
     * @param Scope $scope
     * @return string[]
     */
    public function processNode(Node $node, Scope $scope): array
    {
        $methodName = $node->name->toString();
        // 'get' または 'post' で始まっているかをチェック
        if (!preg_match('/^(get|post)/', $methodName)) {
            return [sprintf(
                'メソッドの名前はgetかpostで始めてください)];
        }
        return [];
    }
}

実際に作成するのは以下の二種類です。

  • RuleTestCaseを継承した、テストケースを記載するファイル
  • 検証用のPHPファイル

まずは検証用のPHPファイルを用意しました。

TestObject
<?php
namespace Path\to\Project\test\data;

class TestObject
{
    /**
     * get始まりなのでOK
     */
    public function getTest() {}
    
    /**
     * post始まりなのでOK
     */
    public function postTest(){}
    
    /**
     * 始まりがgetでもpostでもないので始まりなのでNG
     */
    public function fetchTest(){}
}

続いて、RuleTestCaseを継承してUnitTestを作成します。

<?php
namespace Path\to\Project\test\;

use PHPStan\Testing\RuleTestCase;
use Path\to\Project\rule\MethodNameRule;

class MethodNameRuleTest extends RuleTestCase
{
    protected function getRule(): \PHPStan\Rules\Rule
    {
        // ポイント1: 今回テストしたいルールを指定
        return new MethodNameRule();
    }

    /**
     * ポイント2: PHPUnitのルールでテストケースを記載
     */
    public function test_メソッド名はpostかgetから始まってないといけない(): void
    {
        // ポイント3: analyseメソッドを用いてテストを定義
        $this->analyse(
            [__DIR__ . '/data/Hoge.php'],
            [
                ['メソッドの名前はgetかpostで始めてください!', 19] // 期待値と行数
            ]
        );
    }
}

実行はPHPUnitのコマンドでOKです。
無事に実行できました!

> vendor/bin/phpunit .\src\test
PHPUnit 11.5.2 by Sebastian Bergmann and contributors.
Runtime:       PHP 8.2.17
.                                                                   1 / 1 (100%)
Time: 00:00.588, Memory: 36.00 MB
OK (1 test, 1 assertion)

終わりに

今回はPHPStanのカスタムルールのテストケースを作成しました。
サクッとかけて簡単なので、書いてみてはいかがでしょうか。

ここまでご覧いただきありがとうございました!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?