Pestとは? PHPUnitより書きやすいPHPテストフレームワークの特徴と始め方

目次

「PHPのテスト、書く気にならない問題」を解決するフレームワーク

PHPでテストを書こうとPHPUnitを開いたら、クラス定義、メソッド名の命名規則、$this->assert...の長い記述…。1つのテストケースを書くだけで10行以上のボイラープレートが必要。「テストが大事なのは分かってるけど、書くのが面倒」という声は、PHP開発者の間で根強くあります。

その問題を解決するために生まれたのがPestです。PHPUnitの上に構築された薄いラッパーで、Jest(JavaScript)やRSpec(Ruby)のようなシンプルな記法でPHPのテストが書けます。Laravelでは公式にサポートされており、新規プロジェクトではPestがデフォルトの選択肢になりつつあります。

Pestとは? ― PHPUnitをラップした「書きやすい」テストフレームワーク

Pest(公式サイト)は、Nuno Maduro氏が開発したPHP向けテストフレームワークです。内部的にはPHPUnitが動いているので、PHPUnitの全機能とエコシステムがそのまま使えます。違うのは書き方だけ。

公式が掲げるコンセプトは「Less boilerplate, more intent(ボイラープレートを減らし、意図に集中する)」。クラス定義やメソッド宣言を省略し、「何をテストしたいか」だけを書く設計です。

PHPUnitとの違い ― 同じテストを比べてみる

百聞は一見にしかず。同じテストをPHPUnitとPestで書き比べてみましょう。

PHPUnit

// tests/Feature/PostTest.php(PHPUnit)
namespace Tests\Feature;

use Tests\TestCase;
use App\Models\User;
use App\Models\Post;

class PostTest extends TestCase
{
    public function test_authenticated_user_can_create_post(): void
    {
        $user = User::factory()->create();

        $response = $this->actingAs($user)->postJson('/api/posts', [
            'title' => 'テスト記事',
            'body'  => 'テスト本文です',
        ]);

        $response->assertStatus(201);
        $this->assertDatabaseHas('posts', ['title' => 'テスト記事']);
    }

    public function test_unauthenticated_user_cannot_create_post(): void
    {
        $response = $this->postJson('/api/posts', [
            'title' => 'テスト記事',
            'body'  => 'テスト本文です',
        ]);

        $response->assertStatus(401);
    }
}

Pest

// tests/Feature/PostTest.php(Pest)
use App\Models\User;

it('認証済みユーザーが記事を作成できる', function () {
    $user = User::factory()->create();

    $this->actingAs($user)->postJson('/api/posts', [
        'title' => 'テスト記事',
        'body'  => 'テスト本文です',
    ])->assertStatus(201);

    $this->assertDatabaseHas('posts', ['title' => 'テスト記事']);
});

it('未認証ユーザーは記事を作成できない', function () {
    $this->postJson('/api/posts', [
        'title' => 'テスト記事',
        'body'  => 'テスト本文です',
    ])->assertStatus(401);
});

クラス定義、namespace宣言、メソッド宣言が消え、テストの意図だけが残っています。it()の第一引数が日本語でテストの説明を書けるので、何をテストしているかが一目瞭然です。

セットアップ方法

Laravel(推奨)

Laravel 11以降では、laravel newでプロジェクトを作成する際にPestを選択できます。既存プロジェクトに後から入れる場合は以下の通り。

# Pestと Laravelプラグインをインストール
composer require pestphp/pest --dev
composer require pestphp/pest-plugin-laravel --dev

# Pestの初期設定(tests/Pest.phpが生成される)
./vendor/bin/pest --init

# テスト実行
./vendor/bin/pest

素のPHP(Laravel以外)

composer require pestphp/pest --dev
./vendor/bin/pest --init
./vendor/bin/pest

PHPUnitのphpunit.xmlがそのまま使えるので、既存の設定を変更する必要はありません。

基本的なテストの書き方

test() と it()

Pestにはtest()it()の2つの書き方があります。どちらも同じ動作で、好みの問題です。

// test() 形式
test('税込計算が正しい', function () {
    expect(calcTaxIncluded(1000))->toBe(1100);
});

// it() 形式(英語で読みやすい)
it('calculates tax included price correctly', function () {
    expect(calcTaxIncluded(1000))->toBe(1100);
});

expect()(Pestのアサーション)

PHPUnitの$this->assertEquals()の代わりに、expect()でチェーン記法のアサーションが書けます。

// PHPUnit式
$this->assertEquals('hello', $result);
$this->assertCount(3, $items);
$this->assertTrue($user->isAdmin());

// Pest式(expect)
expect($result)->toBe('hello');
expect($items)->toHaveCount(3);
expect($user->isAdmin())->toBeTrue();

データセット(パラメータ化テスト)

複数のパターンをまとめてテストしたい時に便利な機能です。

it('バリデーションが正しく動作する', function (string $field, mixed $value) {
    $this->postJson('/api/posts', [$field => $value])
         ->assertUnprocessable()
         ->assertJsonValidationErrors($field);
})->with([
    'タイトルが空' => ['title', ''],
    'タイトルが長すぎ' => ['title', str_repeat('a', 256)],
    '本文が空' => ['body', ''],
]);

PHPUnitの@dataProviderと同じことが、->with()のチェーンだけで書けます。

PHPUnitから移行すべき? 判断基準

状況 おすすめ
Laravelの新規プロジェクト ✅ Pest(公式サポートあり、デフォルト推奨)
既存のPHPUnitテストが大量にある △ 段階的に移行(新しいテストだけPestで書く)
Laravel以外のPHPプロジェクト ○ Pestは使えるが、プラグインの恩恵は少ない
チームにPHPUnitの知見しかない △ 学習コストは低いが、チーム合意を取ってから

PestはPHPUnitの上で動くので、同じプロジェクト内にPHPUnitのテストとPestのテストが共存できます。「全部書き換える」必要はなく、新しく書くテストからPestにすれば無理なく移行できます。

PHPテストの理解を深める関連記事

まとめ:Pestは「PHPのテストを書く気にさせてくれる」フレームワーク

  • Pestとは、PHPUnitの上に構築された、シンプルな記法でテストが書けるPHPテストフレームワーク
  • クラス定義・メソッド宣言が不要it()expect()でテストの意図だけを書く
  • PHPUnitと完全互換。同じプロジェクト内で共存でき、段階的に移行可能
  • Laravelでは公式サポート。新規プロジェクトならPestが第一選択肢
  • データセット機能で、パラメータ化テストも->with()のチェーンで書ける

テストを書かない理由が「面倒だから」なら、Pestを試してみてください。書く量が半分以下になるだけで、テストに対する心理的ハードルが驚くほど下がります。まずは1ファイル、1テストケースから。it('動く', function () { expect(true)->toBeTrue(); }); ― これが最初の一歩です。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次