Suite単位でLaravelテストを整理してみた

2025.11.04 09:00
2025.10.22 09:22
Suite単位でLaravelテストを整理してみた

Laravelのテストって、最初は FeatureUnit に分ければいいと思ってたんですよね。
でも実際にプロジェクトが育ってくると、「このテスト、どっちでもないな…」が増えてくる。
そこで最近は Suite(スイート)単位 で整理するようにしてみました。

Feature と Unit の分け方が限界にきた話

Laravel標準の構成ってこうですよね。

tests/
├── Feature/
└── Unit/

最初はこれでいいんですが、DDD構成を取り入れると
「Application層のテスト」や「InfrastructureのDBクエリテスト」など、
どっちにも入れにくいテスト が増えてきます。

結果、「とりあえずFeatureに入れるか…」となって、
あとから探しづらくなるんですよね。

Suite方式とは

Suite方式は、Laravelのレイヤ構成そのままにテストを並べるやり方です。

tests/Suite/
├── Domain/
├── Application/
├── Infrastructure/
│   └── Queries/
└── Presentation/

それぞれが1つのテストスイート(まとまり)として機能します。
phpunit.xml<testsuite> タグを使えば、レイヤ単位で実行も可能です。

phpunit.xml の設定例

<testsuites>
  <testsuite name="Domain">
    <directory suffix="Test.php">./packages/Tool/General/tests/Suite/Domain</directory>
  </testsuite>

  <testsuite name="Application">
    <directory suffix="Test.php">./packages/Tool/General/tests/Suite/Application</directory>
  </testsuite>

  <testsuite name="Infrastructure">
    <directory suffix="Test.php">./packages/Tool/General/tests/Suite/Infrastructure</directory>
  </testsuite>

  <testsuite name="Presentation">
    <directory suffix="Test.php">./packages/Tool/General/tests/Suite/Presentation</directory>
  </testsuite>
</testsuites>

これで、例えばこんな感じで実行できます。

php artisan test --testsuite=Application
php artisan test --testsuite=Infrastructure

レイヤごとの独立実行ができるので、
「Infraだけ重いから時間あるときに回そう」みたいな運用もしやすいです。

命名ルールは「機能+対象+Test」

テストクラスの命名も少し揃えました。

内容
DomainSpotEntityTest値オブジェクト・ドメインルール
ApplicationSearchSpotUseCaseTest
SpotControllerTest
UseCase単体
InfrastructureDbSpotListQueryTestDBや外部I/O
PresentationSpotControllerTestController経由の動作確認

どこを見ても「何をテストしているか」が分かるようにしています。

アトリビュートで粒度を明示

PHPUnit 10〜では、アノテーションではなくアトリビュートが使えます。
これを活かして、テストの規模感をラベル化しています。

use PHPUnit\Framework\Attributes\Small;
use PHPUnit\Framework\Attributes\Medium;
use PHPUnit\Framework\Attributes\Large;

#[Small]   // 完全にユニットテスト
#[Medium]  // UseCaseやDTOなど、少し外部に依存
#[Large]   // DBやファイルを使う

どんなテストかがコード上で一目でわかるのが地味に便利。

Stub / Fake / TestData の置き場

tests/Suite/Support/Models の下にテスト用モデルを置くようにしました。
このモデルでFactoryを読み出すようにしています。

tests/Suite/Common/
└── Support/
    └── Models/
        ├── StubArea.php
        ├── StubSpot.php
        └── StubNews.php

命名は「StubAreaSection」のように接頭辞型に統一。
ファイル一覧でパッと見て「テスト用だ」とわかるのがポイントです。

実際にやってみて感じたこと

  • 探すのがめちゃくちゃ楽になった(UseCaseがどこか迷わない)
  • テストの重さがレイヤごとに見える
  • CIでSuite単位にジョブを分けられる(Domainは毎回、Infraは夜だけなど)
  • Feature/Unitという分類のモヤモヤが消えた

今の運用ルールまとめ

項目ルール
ディレクトリ構成/tests/Suite/<層名>/...
クラス命名<対象><役割>Test
粒度#[Small] / #[Medium] / #[Large]
テストデータ/tests/Suite/Common/ に Stub/Fake
実行単位Suiteごとに php artisan test --testsuite=

まとめ

LaravelでDDDっぽい構成をやるなら、
テストも「Feature / Unit」じゃなくて「層」で考える方が自然です。
Suite単位に整理すると、どこに書くか迷わないし、CIも分けやすい。

なにより「プロジェクトの構造とテストの構造が一致する」ので、
コードを読む人がすぐに全体像をつかめると思います。

今回は以上です!