PHPのテスト環境構築メモ:PHPUnit・Pest・Codeception

今回は PHP のテスト環境を構築する方法をメモとして残します。Laravel 等のフレームワークでは、プロジェクト作成時にすでにテストの実行が可能になっていますが、今回は素の PHP 環境で 1 から環境を構築していきます。単体テストから、統合 (結合) テスト、E2E (End to End) テストと呼ばれる ブラウザー (の機能) を利用してシステム全体をテストできる環境まで構築します。

各テストパッケージの特徴は以下のようになっています。

  • PHPUnit・・・単体、統合テスト用
  • Pest・・・単体、統合テスト用 (PHPUnit よりも記述が簡単)
  • Codeception・・・E2E テスト用 (単体、統合テストにも対応)

今回の記事を作成するにあたり、以下の講座で勉強させていただきました。英語の講座ですが、Udemy の「トランスクリプション」という機能を使用すると講義内容がテキスト形式で右側に表示されるので、Chrome 等の「翻訳機能」を使用すると日本語で表示されます。Microsoft Edge ブラウザーを使用すればビデオ内の字幕を直接日本語に変換できるようです。

Udemy

PHP Unit Testing with PHPUnit

追加で以下の講座で勉強させていただきました。タイトルの通り1時間半ほどの講義ですが、Pest フレームワークのさまざまな機能の説明が凝縮されています。Laravel 11 とありますが、artisan という CLI コマンドを使用しないのであれば、Laravel 自体は必ずしも必要ではないようです。

Udemy

短時間で Pest テストフレームワークを習得しよう!(with Laravel 11)

今回の記事で使用している環境は以下のようになっています。

  • VSCode・・・Windows版 1.105.1
  • WSL2・・・バージョン 2.6.1.0
  • PHP・・・バージョン 8.3.6
  • PHPUnit・・・バージョン 12.4.0
  • Pest・・・バージョン 4.1.2
  • Codeception・・・バージョン 5.3.2
  • Xdebug・・・バージョン 3.2.0 (コードカバレッジ計測に使用)
  • PCOV・・・バージョン 1.0.11 (コードカバレッジ計測用パッケージ)

この記事は Windows の WSL2 を使用して作成していますので、実際に記事の内容を試される場合はご使用の環境によっては不必要な設定があるかもしれません。お手数ですがご使用の環境に応じて環境補正をお願いいたします。また、現在最新の Pest (バージョン 4.x) を使用するには、PHPのバージョン 8.3 以上が必要となります。

サンプルアプリを作成します

テスト用のサンプルとして、簡単な電卓アプリを作成します。WSL2 のコンソール画面で任意のフォルダ (php-calculator 等) を作成して移動します。「code .」と入力して VSCode を起動します。VSCode が起動しない場合は、こちらの記事等を参照して設定してみてください。また、各種フレームワークをインストールするのに、「composer」というパッケージマネージャが必要となりますので実際に試されたい場合は、こちらの記事等を参照してインストールしてください。

cd ~
mkdir php-calculator ; cd php-calculator
code .

「public」、「src」、「tests」というフォルダを作成して、「index.php」、「Calculator.php」 というファイルを作成します。

php-calculator/
├─ public/
│  └─ index.php
├─ src/
│  └─ Calculator.php
└─ tests/

「index.php」ファイルに以下のコードを追加します。

<?php

declare(strict_types=1);

require_once __DIR__ . '/../vendor/autoload.php';

use App\Calculator;

$operators = [
    'add' => '+',
    'sub' => '−',
    'mul' => '×',
    'div' => '÷',
];

$result = null;
$error  = null;

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $a  = isset($_POST['a']) ? (float)$_POST['a'] : 0.0;
    $b  = isset($_POST['b']) ? (float)$_POST['b'] : 0.0;
    $op = $_POST['op'] ?? 'add';

    $calc = new Calculator();
    try {
        $result = $calc->calc($a, $b, $op);
    } catch (Throwable $e) {
        $error = $e->getMessage();
    }
}
?>
<!doctype html>
<html lang="ja">

<head>
    <meta charset="utf-8">
    <title>PHP 電卓(サンプル)</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        body {
            font-family: system-ui, sans-serif;
            margin: 2rem;
        }

        form {
            display: grid;
            gap: .8rem;
            max-width: 360px;
        }

        input,
        select,
        button {
            padding: .6rem;
            font-size: 1rem;
        }

        .result {
            margin-top: 1rem;
            font-weight: bold;
        }

        .error {
            color: #b00020;
        }
    </style>
</head>

<body>
    <h1>PHP 電卓(フォーム送信型)</h1>

    <form method="post">
        <label>
            数値A
            <input type="number" name="a" step="any" value="<?= htmlspecialchars($_POST['a'] ?? '0', ENT_QUOTES) ?>">
        </label>

        <label>
            演算子
            <select name="op">
                <?php foreach ($operators as $k => $label): ?>
                    <option value="<?= $k ?>" <?= (($_POST['op'] ?? 'add') === $k) ? 'selected' : '' ?>>
                        <?= $label ?>
                    </option>
                <?php endforeach; ?>
            </select>
        </label>

        <label>
            数値B
            <input type="number" name="b" step="any" value="<?= htmlspecialchars($_POST['b'] ?? '0', ENT_QUOTES) ?>">
        </label>

        <button type="submit">計算する</button>
    </form>

    <?php if ($error): ?>
        <p class="result error">エラー: <?= htmlspecialchars($error, ENT_QUOTES) ?></p>
    <?php elseif ($result !== null): ?>
        <p class="result">結果: <span id="result"><?= $result ?></span></p>
    <?php endif; ?>
</body>

</html>

「Calculator.php」ファイルの内容は以下のようになっています。

<?php

declare(strict_types=1);

namespace App;

final class Calculator
{
    public function calc(float $a, float $b, string $op): float
    {
        return match ($op) {
            'add' => $a + $b,
            'sub' => $a - $b,
            'mul' => $a * $b,
            'div' => $b == 0.0 ? throw new \InvalidArgumentException('Division by zero') : $a / $b,
            default => throw new \InvalidArgumentException('Unknown operator'),
        };
    }
}

この段階ではまだ実行できません。次のセクションの設定後に実行できるようになります。

Pest と PHPUnit をインストールします

次に単体・統合テスト環境を構築していきます。VSCode で Ctrl + @ と入力してコンソール画面を開いて、以下のコマンドを実行して「Pest」と「PHPUnit」パッケージをインストールします。Pest は PHPUnit をベースに作成されているので、Pest パッケージをインストールすると PHPUnit もインストールされるようです。

composer require --dev pestphp/pest

インストールの途中で 、Pest のプラグインを実行してもいいか聞かれますので「y」を入力します。

pestphp/pest-plugin contains a Composer plugin which is currently not in your allow-plugins config. See https://getcomposer.org/allow-plugins
Do you trust "pestphp/pest-plugin" to execute code and wish to enable it now? (writes "allow-plugins" to composer.json) [y,n,d,?] y

以上でインストールは完了です。コンソール画面に以下のように入力して動作確認をしておきます。

vendor/bin/pest --version
vendor/bin/phpunit --version

以下のようなエラーが出る場合は、プロジェクトフォルダ内に「tests」というフォルダがあるかご確認ください。

user01@DESKTOP-CQEA49P:~/php-calculator$ vendor/bin/pest --version

   Pest\Exceptions\FatalException 

  The test directory [/home/user01/php-calculator/tests/] does not exist.

  at vendor/pestphp/pest/src/Bootstrappers/BootFiles.php:45
     41▕         $rootPath = TestSuite::getInstance()->rootPath;
     42▕         $testsPath = $rootPath.DIRECTORY_SEPARATOR.testDirectory();
     43▕ 
     44▕         if (! is_dir($testsPath)) {
  ➜  45▕             throw new FatalException(sprintf('The test directory [%s] does not exist.', $testsPath));
     46▕         }
     47▕ 
     48▕         foreach (self::STRUCTURE as $filename) {
     49▕             $filename = sprintf('%s%s%s', $testsPath, DIRECTORY_SEPARATOR, $filename);


user01@DESKTOP-CQEA49P:~/php-calculator$ 

特にエラーが無いようでしたら以下のコマンドを実行して Pest を初期化します。

vendor/bin/pest --init

初期化処理を行うと以下のフォルダとファイルが作成されます。「Unit」フォルダ内に単体テスト、「Feature」フォルダ内に統合テストを書くようです。

php-calculator/
├─ tests/
│  ├─ Feature/
│  │  └─ ExampleTest.php
│  ├─ Unit/
│  │  └─ ExampleTest.php
│  ├─ Pest.php
│  └─ TestCase.php
└─ phpunit.xml

このままではテスト実行時にエラーになるので、「composer.json」ファイルを以下のように修正して「autoloader」という仕組みを有効にします。(15 ~ 19 行目) 追加でソースファイル側の autoloader も設定しておきます。(10 ~ 14 行目) autoloader の仕組みについては、こちらのサイト様で詳しく説明されています。

{
  "require-dev": {
    "pestphp/pest": "^4.1"
  },
  "config": {
    "allow-plugins": {
      "pestphp/pest-plugin": true
    }
  },
  "autoload": {
    "psr-4": {
      "App\\": "src/"
    }
  },
  "autoload-dev": {
    "psr-4": {
      "Tests\\": "tests/"
    }
  }
}

設定を追加したら、VSCode のコンソール画面で以下のコマンドを実行します。このコマンドを実行すると「vendor」フォルダ内に「autoload.php」というファイルが作成されます。このファイルを読み込む事で、実際に関数が定義されているファイルを明示的に読み込む必要がなくなります。

composer dump-autoload

以上で設定は終了です。コンソール画面で「vendor/bin/pest」または「vendor/bin/pest tests」と入力するとテストが実行されます。

user01@DESKTOP-CQEA49P:~/php-calculator$ vendor/bin/pest tests

   PASS  Tests\Feature\ExampleTest
  ✓ example                                                                   0.01s  

   PASS  Tests\Unit\ExampleTest
  ✓ example                                                                   0.02s  

  Tests:    2 passed (2 assertions)
  Duration: 0.14s

user01@DESKTOP-CQEA49P:~/php-calculator$ 

アプリを実行するには、VSCode のコンソール画面に以下のように入力して、ブラウザーの URL 欄に「127.0.0.1:8000」と入力します。

php -S 127.0.0.1:8000 -t public

Pest は PHPUnit のテストコードも実行できるので、Pest コマンドだけを使用する場合はこのままでもいいのですが、「vendor/bin/phpunit tests」と入力すると今度は逆に PHPUnit が Pest のテストコードも実行しようとしてエラーになります。以下のように「Pest」と「PhpUnit」フォルダにそれぞれのテストケースを分けておけば PHPUnit コマンドも使用できます。「Pest.php」ファイルは移動しないでそのままにしておきます。

tests
├─ Pest
│   ├─ Feature
│   │   └─ ExampleTest.php
│   └─ Unit
│       └─ ExampleTest.php
├─ PhpUnit
│   └─ ExampleTest.php
├─ Pest.php
└─ TestCase.php

PHPUnit コマンドを実行する場合は、以下のように入力します。

vendor/bin/phpunit tests/PhpUnit
Codeception をインストールします

E2E (End to End) テスト用に「Codeception」をインストールします。Codeception も PHPUnit をベースにして構築されています。単体や統合テストにも使用できるようですが、単体や統合テストは Pest を使用した方が簡潔に記述できるようです。逆に本物のブラウザーを使用してテストを行いたい場合は Codeception を利用した方が簡単に実現できるようです。

Codeception をインストールするには、VSCode のターミナル画面に以下のように入力します。

composer require --dev codeception/codeception

ブラウザー操作も行いたい場合は以下のパッケージもインストールしておきます。

composer require --dev codeception/module-webdriver

インストールが完了したら続けて以下のコマンドを入力します。

vendor/bin/codecept bootstrap

このコマンドによりアプリフォルダの直下と、tests フォルダ内に以下のフォルダとファイルが作成されます。

<app>/
├─ tests/
│  ├─ _output/
│  ├─ Acceptance/
│  ├─ Functional/
│  ├─ Support/
│  │  ├─ Data/
│  │  ├─ Helper/
│  │  ├─ _generated/
│  │  │   ├─ AcceptanceTesterActions.php
│  │  │   ├─ FunctionalTesterActions.php
│  │  │   └─ UnitTesterActions.php
│  │  ├─ AcceptanceTester.php
│  │  ├─ FunctionalTester.php
│  │  └─ UnitTester.php
│  ├─ Unit/
│  ├─ Acceptance.suite.yml
│  ├─ Functional.suite.yml
│  └─ Unit.suite.yml
└─ codeception.yml

Codeception は Pest 等のテストスイートと共存可能ですが、フォルダやファイルが多いので、tests フォルダ内に「Codeception」というフォルダを作成して生成されたフォルダとファイルを以下のように移動します。「codeception.yml」ファイルはそのままにしておきます。

<app>/
├─ tests/
│  └─ Codeception/
│    ├─ _output/
│    ├─ Acceptance/
│    ├─ Functional/
│    ├─ Support/
│    ├─ Unit/
│    ├─ Acceptance.suite.yml
│    ├─ Functional.suite.yml
│    └─ Unit.suite.yml
└─ codeception.yml

「codeception.yml」ファイルを以下のように修正します。

namespace: Tests
support_namespace: Support
paths:
    tests: tests/Codeception
    output: tests/Codeception/_output
    data: tests/Codeception/Support/Data
    support: tests/Codeception/Support
    envs: tests/Codeception/_envs
actor_suffix: Tester
extensions:
    enabled:
        - Codeception\Extension\RunFailed

以上で設定は終了です。ターミナル画面に以下のコマンドを入力するとテストが実行されます。

vendor/bin/codecept run
単体テストの記述例

テストを行う準備ができましたので、実際にテストケースを記述してみます。以下の計算ロジックのテストケースを「PHPUnit」と「Pest」で記述します。(実際のテストの記述方法等に付きましては、お手数ですがそれぞれの仕様書またはオンライン講座等をご参照ください。)

final class Calculator
{
    public function calc(float $a, float $b, string $op): float
    {
        return match ($op) {
            'add' => $a + $b,
            'sub' => $a - $b,
            'mul' => $a * $b,
            'div' => $b == 0.0 ? throw new \InvalidArgumentException('Division by zero') : $a / $b,
            default => throw new \InvalidArgumentException('Unknown operator'),
        };
    }
}

テストの内容は同じで、加算と例外発生処理のテストケースになっています。(比較のため PHPUnit と Pest 両方のテストケースを記述していますが、実際の開発時にはどちらかで記述すれば充分です。)

・PHPUnit の記述例
<?php

declare(strict_types=1);

use PHPUnit\Framework\TestCase;
use App\Calculator;

final class CalculatorTest extends TestCase
{
    public function testAdd(): void
    {
        $c = new App\Calculator();
        $this->assertSame(5.0, $c->calc(2, 3, 'add'));
    }

    public function testDivByZero(): void
    {
        $this->expectException(InvalidArgumentException::class);
        (new Calculator())->calc(1, 0, 'div');
    }
}
・Pest の記述例
<?php

use App\Calculator;

test('adds numbers', function () {
    expect((new Calculator())->calc(2, 3, 'add'))->toBe(5.0);
});

test('throws on division by zero', function () {
    (new Calculator())->calc(1, 0, 'div');
})->throws(InvalidArgumentException::class);

それぞれのテスト実行結果は以下のようになります。

・PHPUnit テストの実行結果
user01@DESKTOP-CQEA49P:~/php-calculator$ vendor/bin/phpunit tests/PhpUnit
PHPUnit 12.4.0 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.3.6
Configuration: /home/user01/php-calculator/phpunit.xml

..                                                                  2 / 2 (100%)

Time: 00:00.011, Memory: 16.00 MB

OK (2 tests, 2 assertions)
user01@DESKTOP-CQEA49P:~/php-calculator$ 
・Pest テストの実行結果
user01@DESKTOP-CQEA49P:~/php-calculator$ vendor/bin/pest tests/Pest

   PASS  Tests\Pest\Unit\CalculatorTest
  ✓ adds numbers                                                                                                          0.01s  
  ✓ throws on division by zero

  Tests:    2 passed (2 assertions)
  Duration: 0.10s

user01@DESKTOP-CQEA49P:~/php-calculator$ 
カバレッジの測定 (Xdebug 版)

このセクションでは「Xdebug」を用いたカバレッジの測定方法をご説明します。Xdebug のインストール方法につきましては、お手数ですがこちらの記事等をご参照ください。

・PHPUnit カバレッジの実行

コンソール画面に以下のコマンドを入力するとカバレッジが測定されます。

XDEBUG_MODE=coverage vendor/bin/phpunit tests/PhpUnit --coverage-text

実行結果は以下のようになります。

user01@DESKTOP-CQEA49P:~/php-calculator$ XDEBUG_MODE=coverage vendor/bin/phpunit tests/PhpUnit --coverage-text
PHPUnit 12.4.0 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.3.6 with Xdebug 3.2.0
Configuration: /home/user01/php-calculator/phpunit.xml

..                                                                  2 / 2 (100%)

Time: 00:00.035, Memory: 16.00 MB

OK (2 tests, 2 assertions)


Code Coverage Report:  
  2025-10-24 08:59:10  
                       
 Summary:              
  Classes:  0.00% (0/1)
  Methods:  0.00% (0/1)
  Lines:   71.43% (5/7)

App\Calculator
  Methods:   0.00% ( 0/ 1)   Lines:  71.43% (  5/  7)
user01@DESKTOP-CQEA49P:~/php-calculator$ 

HTML 形式で出力したい場合は以下のように入力します。

XDEBUG_MODE=coverage vendor/bin/phpunit tests/PhpUnit --coverage-html coverage-html

生成された「coverage-html」フォルダ内にある「index.html」ファイルを開くとカバレッジの実行結果が表示されます。

・Pest カバレッジの実行

コンソール画面に以下のコマンドを入力するとカバレッジが測定されます。

XDEBUG_MODE=coverage vendor/bin/pest tests/Pest --coverage

実行結果は以下のようになります。

user01@DESKTOP-CQEA49P:~/php-calculator$ XDEBUG_MODE=coverage vendor/bin/pest tests/Pest --coverage

   PASS  Tests\Pest\Unit\CalculatorTest
  ✓ adds numbers                                                                                   0.01s  
  ✓ throws on division by zero

  Tests:    2 passed (2 assertions)
  Duration: 0.07s

  Calculator ............................................................................ 13..14 / 71.4%  
  ──────────────────────────────────────────────────────────────────────────────────────────────────────  
                                                                                           Total: 71.4 %  

user01@DESKTOP-CQEA49P:~/php-calculator$ 

HTML 形式で出力したい場合は以下のように入力します。

XDEBUG_MODE=coverage vendor/bin/pest tests/Pest --coverage-html

生成された「--cache-directory」フォルダ内にある「index.html」ファイルを開くとカバレッジの実行結果が表示されます。

カバレッジの測定 (PCOV 版)

カバレッジの測定には他に「PCOV」と呼ばれるツールなどがあります。実行速度は PCOV の方が高速に動作するようです。制限事項として Xdebug との共存 (同時実行) はできないようです。Xdebug が有効になっている場合は設定を無効にするか、コマンド入力時に一時的に無効にする必要があります。コマンドの先頭に「XDEBUG_MODE=off」を追加すると一時的に Xdebug を無効にできます。

・PCOV のインストール

WSL2 で Ubuntu を使用している場合は以下のように入力するとインストールされます。

sudo apt install php-pcov
# または
sudo apt install php8.3-pcov
・PHPUnit カバレッジの実行

コンソール画面に以下のコマンドを入力するとカバレッジが測定されます。

XDEBUG_MODE=off vendor/bin/phpunit tests/PhpUnit --coverage-text

実行結果は以下のようになります。

user01@DESKTOP-CQEA49P:~/php-calculator$ XDEBUG_MODE=off vendor/bin/phpunit tests/PhpUnit --coverage-text
PHPUnit 12.4.0 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.3.6 with PCOV 1.0.11
Configuration: /home/user01/php-calculator/phpunit.xml

..                                                                  2 / 2 (100%)

Time: 00:00.002, Memory: 18.00 MB

OK (2 tests, 2 assertions)


Code Coverage Report:  
  2025-10-27 00:14:45  
                       
 Summary:              
  Classes:  0.00% (0/1)
  Methods:  0.00% (0/1)
  Lines:   71.43% (5/7)

App\Calculator
  Methods:   0.00% ( 0/ 1)   Lines:  71.43% (  5/  7)
user01@DESKTOP-CQEA49P:~/php-calculator$ 

HTML 形式で出力したい場合は以下のように入力します。

XDEBUG_MODE=off vendor/bin/phpunit tests/PhpUnit --coverage-html coverage-html

生成された「coverage-html」フォルダ内にある「index.html」ファイルを開くとカバレッジの実行結果が表示されます。

・Pest カバレッジの実行

コンソール画面に以下のコマンドを入力するとカバレッジが測定されます。

XDEBUG_MODE=off vendor/bin/pest tests/Pest --coverage

実行結果は以下のようになります。

user01@DESKTOP-CQEA49P:~/php-calculator$ XDEBUG_MODE=off vendor/bin/pest tests/Pest --coverage

   PASS  Tests\Pest\Unit\CalculatorTest
  ✓ adds numbers                                                                                       0.01s  
  ✓ throws on division by zero

  Tests:    2 passed (2 assertions)
  Duration: 0.18s

  Calculator ................................................................................ 13..14 / 71.4%  
  ──────────────────────────────────────────────────────────────────────────────────────────────────────────  
                                                                                               Total: 71.4 %  

user01@DESKTOP-CQEA49P:~/php-calculator$ 

HTML 形式で出力したい場合は以下のように入力します。

XDEBUG_MODE=off vendor/bin/pest tests/Pest --coverage-html

生成された「--cache-directory」フォルダ内にある「index.html」ファイルを開くとカバレッジの実行結果が表示されます。

・Xdebug を無効にするには

「/etc/php/8.3/mods-available/xdebug.ini」ファイルを開いて設定をコメントアウトします。

[xdebug]
#zend_extension=/usr/lib/php/20230831/xdebug.so
#xdebug.mode = debug,develop,trace
#xdebug.start_with_request = yes
#xdebug.client_port = 9003

以下のコマンドでWEB サーバーを再起動すると Xdebug が無効になります。
この設定にした場合は、カバレッジ実行コマンドの先頭にある「XDEBUG_MODE=off」が不要になります。

sudo systemctl restart apache2
E2E テストの実行方法
・テストファイルを作成します

こちらのチュートリアルを参考にして、E2E (受け入れ) テストファイルを作成します。VSCode のターミナル画面を開いて以下のコマンドを入力します。「First」の部分は任意のファイル名に変更可能です。

vendor/bin/codecept generate:cest Acceptance First

コマンドを実行すると以下の位置に「FirstCest.php」というテストファイルが作成されます。

<app>/
└─ tests/
   └─ Codeception/
     └─ Acceptance/
       └─ FirstCest.php

「FirstCest.php」ファイルを開いて以下のテストを追加します。テストの内容はトップページを開いて、「PHP」という文字列があるか確認するという動作になっています。これ以外にもクリックや文字列の入力、JavaScript の実行など一般的なブラウザー操作はほとんど行えるようです。詳しくはこちらの公式ページをご覧ください。

<?php

declare(strict_types=1);


namespace Tests\Acceptance;

use Tests\Support\AcceptanceTester;

final class FirstCest
{
    public function _before(AcceptanceTester $I): void
    {
        // Code here will be executed before each test.
    }

    public function tryToTest(AcceptanceTester $I): void
    {
        // Write your tests here. All `public` methods will be executed as tests.
    }

    public function frontpageWorks(AcceptanceTester $I)
    {
        $I->amOnPage('/');
        $I->see('PHP');
    }
}

VSCode で「Ctrl + Shift + @」と入力して新しいターミナル画面を開いて、以下のコマンドを入力して PHP の簡易 WEB サーバーを起動します。

php -S localhost:8000 -t public
・簡易エミュレーターを使用して E2E テストを行います

「tests/Codeception/Acceptance.suite.yml」ファイルを開いて以下のように修正します。

# Codeception Acceptance Test Suite Configuration
#
# Perform tests in a browser by either emulating one using PhpBrowser, or in a real browser using WebDriver.
# If you need both WebDriver and PhpBrowser tests, create a separate suite for each.

actor: AcceptanceTester
modules:
    enabled:
        - PhpBrowser:
            url: http://localhost:8000
# Add Codeception\Step\Retry trait to AcceptanceTester to enable retries
step_decorators:
    - Codeception\Step\ConditionalAssertion
    - Codeception\Step\TryTo
    - Codeception\Step\Retry

VSCode のターミナル画面に以下のコマンドを入力すると受け入れテストが実行されます。

vendor/bin/codecept run --steps

実行結果は以下のようになります。

user01@DESKTOP-CQEA49P:~/php-calculator$ vendor/bin/codecept run --steps
Codeception PHP Testing Framework v5.3.2 https://stand-with-ukraine.pp.ua

Tests.Acceptance Tests (2) ---------------------------------------------
FirstCest: Try to test
Signature: Tests\Acceptance\FirstCest:tryToTest
Test: tests/Codeception/Acceptance/FirstCest.php:tryToTest
Scenario --
 PASSED 

FirstCest: Frontpage works
Signature: Tests\Acceptance\FirstCest:frontpageWorks
Test: tests/Codeception/Acceptance/FirstCest.php:frontpageWorks
Scenario --
 I am on page "/"
 I see "PHP"
 PASSED 

------------------------------------------------------------------------

Tests.Functional Tests (0) ---------------------------------------------
------------------------------------------------------------------------

Tests.Unit Tests (0) ---------------------------------------------------
------------------------------------------------------------------------
Time: 00:00.158, Memory: 14.00 MB

OK (2 tests, 1 assertion)
user01@DESKTOP-CQEA49P:~/php-calculator$ 
・ブラウザーを使用して E2E テストを行います

実際のブラウザーを使用して、E2E テストを行います。テスト構成は以下のようになっています。WSL2 上の Codeception から Selenium Server を介して Chrome ブラウザーを操作します。Codeception 以外は Windows 上で動作します。

Selenium Server を実行するには Java が必要です。お使いの PC にインストールされていない場合は、こちらのリンクからダウンロードできます。ダウンロードした msi ファイルをダブルクリックしてすべてデフォルト設定でインストールしてください。

インストールが完了したら PowerShell やコマンドプロンプトで「java -version」と入力するとバージョンが表示されます。

C:\Windows\System32>java -version
openjdk version "25" 2025-09-16 LTS
OpenJDK Runtime Environment Temurin-25+36 (build 25+36-LTS)
OpenJDK 64-Bit Server VM Temurin-25+36 (build 25+36-LTS, mixed mode, sharing)

C:\Windows\System32>

こちらのリンクから Selenium Server をダウンロードします。「c:\Selenium」等のフォルダを作成してダウンロードされたファイル (selenium-server.jar) を作成したフォルダに移動します。

こちらのリンクから ChromeDriver のダウンロード用 URL をコピーしてブラウザーで開いてダウンロードします。ダウンロードしたファイルを作成した「c:\Selenium」フォルダ内に展開します。

次にこちらのサイト様等を参考にして「c:\Selenium」にパスを通しておきます。環境変数の設定画面は、VSCode で Ctrl + @ キーと押して表示されるターミナル画面や Windows のターミナル画面で以下のように入力すると「システムのプロパティ」画面が表示されるようなので、この画面の「環境変数(N)」ボタンから移動できます。

control sysdm.cpl

「c:\Selenium」フォルダ内に「ss.bat」というファイルを作成して以下のように記述します。このファイルをダブルクリックすると Selenium Server が起動します。終了するには起動したターミナル画面で Ctrl + C キーを入力して、表示されたプロンプトで「y」を入力すると停止します。

java -jar selenium-server.jar standalone

WSL2 から Windows 上の Selenium Server にアクセスできるようにファイアウォールを設定します。管理者権限で PowerShell またはコマンドプロンプトを起動して以下のコマンドを実行します。この設定を行うと、WSL2 から Windows の 4444 ポートにアクセスできるようになります。

netsh advfirewall firewall add rule name="4444" protocol=TCP dir=in localport=4444 action=allow

WSL2 側から接続するために必要になるので、Windows の PowerShell かコマンドプロンプトで「ipconfig」コマンドを実行して、PC の IP アドレスを確認します。

C:\Windows\System32>ipconfig

Windows IP 構成


イーサネット アダプター イーサネット:

   接続固有の DNS サフィックス . . . . .:
   IPv4 アドレス . . . . . . . . . . . .: 192.168.11.42
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   デフォルト ゲートウェイ . . . . . . .: 192.168.11.1

Selenium Server を起動してから、WSL2 のコンソール画面で以下のコマンドを実行します。IP アドレスの部分はご自身の環境に合わせて変更してください。何か JSON データが返ってくれば正常にアクセスできています。

curl http://192.168.11.42:4444/status

「tests/Codeception/Acceptance.suite.yml」ファイルを開いて以下のように修正します。12 行目の IP アドレスの部分はご自身の環境に合わせて変更してください。

# Codeception Acceptance Test Suite Configuration
#
# Perform tests in a browser by either emulating one using PhpBrowser, or in a real browser using WebDriver.
# If you need both WebDriver and PhpBrowser tests, create a separate suite for each.

actor: AcceptanceTester
modules:
    enabled:
        - WebDriver:
            url: 'http://localhost:8000'
            browser: chrome
            host: 192.168.11.42
            port: 4444
# Add Codeception\Step\Retry trait to AcceptanceTester to enable retries
step_decorators:
    - Codeception\Step\ConditionalAssertion
    - Codeception\Step\TryTo
    - Codeception\Step\Retry

VSCode のコンソール画面に以下のように入力して、PHP の簡易サーバーを起動します。

php -S 127.0.0.1:8000 -t public

Ctrl + Shift + @ と入力して新しいコンソール画面を開いて、以下のように入力すると E2E テストが実行されます。

vendor/bin/codecept run Acceptance -d

正常にテストが実行された場合は、Windows 側で一瞬 WEB ブラウザーが起動して、VSCode のコンソール画面に以下のメッセージが表示されます。

user01@DESKTOP-CQEA49P:~/php-calculator$ vendor/bin/codecept run Acceptance -d
Codeception PHP Testing Framework v5.3.2 https://stand-with-ukraine.pp.ua

Tests.Acceptance Tests (2) -------------------------------------------------------------------------------
Modules: WebDriver
----------------------------------------------------------------------------------------------------------
FirstCest: Try to test
Signature: Tests\Acceptance\FirstCest:tryToTest
Test: tests/Codeception/Acceptance/FirstCest.php:tryToTest
Scenario --
 PASSED 

FirstCest: Frontpage works
Signature: Tests\Acceptance\FirstCest:frontpageWorks
Test: tests/Codeception/Acceptance/FirstCest.php:frontpageWorks
Scenario --
 I am on page "/"
  [GET] http://localhost:8000/
 I see "PHP"
 PASSED 

----------------------------------------------------------------------------------------------------------
Time: 00:01.201, Memory: 12.00 MB

OK (2 tests, 1 assertion)
user01@DESKTOP-CQEA49P:~/php-calculator$ 

ブラウザーを使用する E2E テストはさまざまなパッケージを使用して実現しているため、各パッケージのバージョンの組み合わせによっては動作しない場合があります。テスト実行時に何かエラーが発生する場合は、以下のようにパッケージのバージョンを明示的に設定してください。

{
    "require-dev": {
        "pestphp/pest": "^4.1",
        "codeception/codeception": "^5.3",
        "codeception/module-webdriver": "^4.0",
        "codeception/module-phpbrowser": "^3.0",
        "codeception/module-asserts": "^3.0"
    },
    "config": {
        "allow-plugins": {
            "pestphp/pest-plugin": true
        }
    },
    "autoload": {
        "psr-4": {
            "App\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    }
}

プロジェクト内の「vendor」フォルダーと「composer.lock」ファイルを削除して、VSCode のコンソール画面に以下のように入力すると指定したバージョンのパッケージがインストールされます。

composer install

以上です。よろしかったらお試しください。