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 にすると各テストごとにトランザクションで巻き戻され、テスト間でデータが汚れません。

確認方法

  1. bootstrap で tests/ 配下と設定ファイルが生成されている
  2. run --steps で各ステップがログに出力される
  3. わざと $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 の受け入れ・機能テストから始めてみてください。

\ 最新情報をチェック /

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。