Codeceptionではじめる PHPの受け入れ・機能テスト入門
概要
PHPのテストというと PHPUnit を思い浮かべる方が多いと思いますが、「ユーザーが実際に画面を操作したときに正しく動くか」を確かめる 受け入れテスト(Acceptance Test) や、フレームワークを通したリクエスト全体を検証する 機能テスト(Functional Test) は、PHPUnit だけだと書き方に迷いがちです。
そこで役立つのが Codeception です。Codeception は「読みやすいシナリオ」でテストを書けることを重視した PHP のテストフレームワークで、Unit / Functional / Acceptance の3種類のテストを1つのツールで扱えます。この記事では導入から最初の受け入れ・機能テストを動かすところまでを入門者向けに解説します。
Codeception の3種類のテスト
| 種類 | 実行のしかた | 速度 | 何を確かめるか |
|---|---|---|---|
| Unit | クラスを直接呼ぶ | 速い | ロジック単体の正しさ |
| Functional | フレームワークを内部で実行(サーバ不要) | 中 | ルーティング〜レスポンスまで |
| Acceptance | 実際のHTTP/ブラウザ経由 | 遅い | 実環境に近い画面操作 |
ポイントは Functional はWebサーバを立てずに動く ことです。フレームワークのカーネルをメモリ上で呼び出してリクエストをシミュレートするため、実ブラウザより高速に「ページ遷移とフォーム送信の一連」を検証できます。一方 Acceptance は本物のHTTPクライアントやブラウザ を使うので、より実環境に近い代わりに遅くなります。
環境
- PHP 8.1 以上
- Composer 導入済み
- Codeception 5.x(記事執筆時点の一例)
バージョンによって記法や必要PHPバージョンが変わるため、導入時は公式ドキュメントで確認してください。
インストール
composer require "codeception/codeception" --dev
Codeception 5.x ではモジュールが分割されているため、使うモジュールを個別に追加します。入門ではJS非対応の軽量HTTPクライアント PhpBrowser とアサーション用 Asserts があれば十分です。
composer require "codeception/module-phpbrowser" --dev composer require "codeception/module-asserts" --dev
プロジェクトの初期化
vendor/bin/codecept bootstrap
実行すると、次のような構成が生成されます。
tests/ ├── Acceptance/ ├── Functional/ ├── Unit/ ├── Support/ │ ├── AcceptanceTester.php │ ├── FunctionalTester.php │ └── UnitTester.php ├── Acceptance.suite.yml ├── Functional.suite.yml └── Unit.suite.yml codeception.yml
XxxTester.php は Actor(アクター) と呼ばれ、「テストの中の登場人物(=ユーザー)」を表します。$I->amOnPage(...) のように、この Actor が画面を操作していくのが Codeception の書き味です。
受け入れテストの設定
tests/Acceptance.suite.yml:
actor: AcceptanceTester
modules:
enabled:
- PhpBrowser:
url: http://localhost:8080
- \Helper\Acceptance
url にはテスト対象アプリのベースURLを指定します。ローカルで php -S localhost:8080 -t public のような開発サーバを立てておくイメージです。
はじめての受け入れテスト
Codeception には Cept(手続き的な1ファイル形式)と Cest(クラス形式)があり、実務ではメソッドごとにシナリオを分けられる Cest が主流です。
vendor/bin/codecept generate:cest Acceptance FirstAcceptance
生成された tests/Acceptance/FirstAcceptanceCest.php を編集します。
<?php
namespace Tests\Acceptance;
use Tests\Support\AcceptanceTester;
class FirstAcceptanceCest
{
public function トップページが表示される(AcceptanceTester $I): void
{
$I->amOnPage('/');
$I->see('ようこそ');
}
public function ログインフォームから遷移できる(AcceptanceTester $I): void
{
$I->amOnPage('/login');
$I->fillField('email', 'user@example.com');
$I->fillField('password', 'password');
$I->click('ログイン');
$I->seeCurrentUrlEquals('/dashboard');
$I->see('ダッシュボード');
}
}
$I->amOnPage() でページを開き、$I->see() で文言を確認、$I->fillField() と $I->click() でフォームを操作——と、やっていることが文章のように読める のが Codeception の魅力です。
実行してみる
# 受け入れスイートだけ実行 vendor/bin/codecept run Acceptance # 各ステップを表示 vendor/bin/codecept run Acceptance --steps
--steps を付けると、Actor が何をしたかが1行ずつ出力され、どこで落ちたかが直感的に分かります。
FirstAcceptanceCest: トップページが表示される Scenario -- I am on page "/" I see "ようこそ" PASS
機能テスト(Functional)を書く
機能テストはWebサーバを立てず、フレームワークを内部で呼び出します。Laravel / Symfony / Yii2 などフレームワークごとに専用モジュールがあります。
tests/Functional.suite.yml(Laravel の例):
actor: FunctionalTester
modules:
enabled:
- Laravel
- \Helper\Functional
テスト本体は受け入れテストとほぼ同じ書き味です。
<?php
namespace Tests\Functional;
use Tests\Support\FunctionalTester;
class ArticleCest
{
public function 記事一覧が取得できる(FunctionalTester $I): void
{
$I->amOnPage('/articles');
$I->seeResponseCodeIs(200);
$I->see('記事一覧');
}
}
同じ $I->amOnPage() でも、Functional はカーネルを直接叩くため高速です。「受け入れで書いたシナリオを、速い機能テストに寄せる」という使い分けができます。
DBの状態を検証する
「登録処理でレコードが本当に作られたか」は Db モジュールで確認します。
composer require "codeception/module-db" --dev
modules:
enabled:
- Db:
dsn: 'mysql:host=127.0.0.1;dbname=app_test'
user: '%DB_USER%'
password: '%DB_PASSWORD%'
cleanup: true
接続情報は環境変数展開(%VAR%)や .env から読み、リポジトリにコミットしないようにしてください。
public function ユーザー登録でレコードが作成される(AcceptanceTester $I): void
{
$I->amOnPage('/signup');
$I->fillField('email', 'new@example.com');
$I->click('登録');
$I->seeInDatabase('users', ['email' => 'new@example.com']);
}
cleanup: true にすると各テストごとにトランザクションで巻き戻され、テスト間でデータが汚れません。
確認方法
bootstrapでtests/配下と設定ファイルが生成されているrun --stepsで各ステップがログに出力される- わざと
$I->see('存在しない文言')に書き換え、テストが 落ちること を確認する
3番目は地味ですが重要です。常にグリーンのテストは、実は何も検証していない可能性があります。
注意点
- JavaScript が必要なら PhpBrowser では不可:JSを含む操作の検証には
WebDriver(Selenium / ヘッドレスブラウザ)が必要です。 - 受け入れテストを増やしすぎない:実ブラウザ経由は遅く壊れやすい。細かい検証はユニット・機能テストに寄せ、受け入れは主要導線に絞る(テストピラミッド)。
- 接続情報を直書きしない:DBパスワード等は環境変数や
.envを使い、コミットしない。 - バージョン差に注意:Codeception 4系と5系で名前空間・必要PHPバージョンが異なります。
まとめ
- Codeception は Unit / Functional / Acceptance を1ツールで扱える
$I->amOnPage()のようにシナリオが読みやすいのが最大の特徴- 受け入れ=実環境に近いが遅い、機能=サーバ不要で速い、で使い分ける
- まずは
bootstrap→ Cest 生成 →run --stepsの流れを掴むのが最短ルート
PHPUnit は書いているけど画面まわりは手動確認のまま、という方は、Codeception の受け入れ・機能テストから始めてみてください。
