PHP入門:PHPUnitでテストをスキップする

スポンサーリンク
PHP入門:PHPUnitでテストをスキップする ノウハウ
PHP入門:PHPUnitでテストをスキップする
この記事は約9分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

今日は、PHPUnitでテストをスキップする方法についてご紹介します。

スポンサーリンク

前提

この記事は下記の記事をベースにしています。

背景

必ずしも、すべてのテストをすべての環境で実行できるわけではないと思います。たとえば、データベースの抽象化レイヤーを考えてみましょう。MySQL ドライバのテストは、MySQL サーバが利用可能でなければ実行できません。

そうした場合に、テストをスキップする方法をご紹介します。

下記に示すテストケースクラス DatabaseTest には、 testConnection() というテストメソッドがひとつあります。テストケースクラスの setUp() テンプレートメソッドで pgsql 拡張モジュールが使用可能かどうかをチェックし、 使用可能でない場合は markTestSkipped() メソッドを使用してテストをスキップします。

修正内容

下記のファイルを更新、もしくは、作成します。下記の各セクションに各ファイルの修正内容を記載しています。

        new file:   19_learn_phpunit/tests/DatabaseTest.php

tests/DatabaseTest.php

下記の内容で新規作成します。

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class DatabaseTest extends TestCase
{
    protected function setUp(): void
    {
        if (!extension_loaded('pgsql')) {
            $this->markTestSkipped(
                'The PostgreSQL extension is not available'
            );
        }
    }

    public function testConnection(): void
    {
        // ...
    }
}

動作確認

下記のコマンドを実施します。

docker compose run -it --rm php-cmd ./vendor/bin/phpunit tests/DatabaseTest.php

下記の結果になれば成功です。

% docker compose run -it --rm php-cmd ./vendor/bin/phpunit tests/DatabaseTest.php
[+] Building 0.0s (0/0)                                                                                                                            
[+] Building 0.0s (0/0)                                                                                                                            
PHPUnit 10.2.6 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.1.12-1ubuntu4.2

S                                                                   1 / 1 (100%)

Time: 00:00.037, Memory: 6.00 MB

OK, but some tests were skipped!
Tests: 1, Assertions: 0, Skipped: 1.

スキップされたテストは、PHPUnit コマンドラインテストランナーの出力で S で示されます。

解説

tests/DatabaseTest.php

このコードは、PHPのユニットテストにおいて、PostgreSQLデータベース接続のテストを行うためのPHPUnitテストケースクラスの例です。PHPUnitはPHP用のテスティングフレームワークであり、テスト駆動開発(TDD)や単体テストの実行に使用されます。

まず、<?php declare(strict_types=1);は、スクリプトの厳格な型宣言を有効にするためのPHPの宣言です。これにより、関数の引数や返り値に対して型を明示的に指定できます。

次に、use PHPUnit\Framework\TestCase;は、PHPUnitフレームワークのTestCaseクラスをインポートしています。これにより、PHPUnitの機能を利用してテストケースを作成できます。

DatabaseTestクラスは、TestCaseクラスを継承しており、PostgreSQLデータベース接続に関連するテストを行うためのテストケースクラスとして定義されています。

protected function setUp(): voidは、PHPUnitのテストのセットアップメソッドです。テストメソッドが実行される前に自動的に呼び出されます。ここでは、PostgreSQL拡張機能がロードされているかどうかを確認しています。もしPostgreSQL拡張機能がロードされていない場合は、markTestSkippedメソッドを呼び出して、テストをスキップします。これは、テスト実行環境にPostgreSQLがインストールされていない場合などに便利です。

最後に、public function testConnection(): voidは、データベース接続をテストするためのテストメソッドです。ただし、実際のテストコード(テストメソッドの中身)はないです。テストメソッドの中には、特定のデータベース接続を確立し、クエリを実行して結果を検証するなどのテストロジックが含まれることを想定していますが、今回は省略しています。

この例では、テストのセットアップでPostgreSQL拡張機能が利用可能かどうかを確認しているため、テストが実行される前に事前条件をチェックしていると言えます。テストメソッド内では、実際のテストコードが書かれるべきです。

属性を使ったテストのスキップ

上記の方法に加え、属性を使用してテストケースに共通する前提条件を表現することも可能です。

  • RequiresFunction(string $functionName) は、指定した名前の関数が宣言されていない場合にテストをスキップします。
  • RequiresMethod(string $className, string $functionName) 指定した名前のメソッドが宣言されていない場合はテストを省略します。
  • RequiresOperatingSystem(string $regularExpression) オペレーティングシステムの名前が、指定した正規表現にマッチしない場合にテストをスキップします。
  • RequiresOperatingSystemFamily(string $operatingSystemFamily) オペレーティングシステムのファミリが指定されたものでない場合にテストをスキップします。
  • RequiresPhp(string $versionRequirement) PHP のバージョンが指定したものと一致しない場合にテストをスキップします。
  • RequiresPhpExtension(string $extension, ?string $versionRequirement) 指定した PHP 拡張モジュールが使用できない場合にテストをスキップします。
  • RequiresPhpunit(string $versionRequirement) PHPUnit のバージョンが指定したものと一致しない場合にテストを省略します。
  • RequiresSetting(string $setting, string $value) 指定した PHP の設定値が指定した値でない場合にテストを省略します。

上で挙げた属性はすべて、PHPUnitFramework の名前空間 PHPUnitAttributes で宣言されています。

今回のテストケースを属性を使って下記のように記述することも可能になります。

<?php declare(strict_types=1);
use PHPUnit\Framework\Attributes\RequiresPhpExtension;
use PHPUnit\Framework\TestCase;

#[RequiresPhpExtension('pgsql')]
final class DatabaseTestUsingAttribute extends TestCase
{
    public function testConnection(): void
    {
        // ...
    }
}
tt

markTestSkippedメソッドを使用する理由

markTestSkippedメソッドは、PHPUnitフレームワークでテストをスキップするために使用される重要なメソッドです。テストをスキップする理由はいくつかあります:

  1. 依存関係の欠如: テストケースが実行に必要な外部の依存関係が存在しない場合に、テストをスキップすることがあります。例えば、特定の拡張機能やサービスがインストールされていない環境でテストを実行しようとした場合に、その拡張機能やサービスが利用できないためにテストをスキップします。
  2. 特定の条件が満たされていない: テストケースが特定の条件を満たす場合にのみ有効である場合に、条件が満たされない場合にテストをスキップすることがあります。例えば、ユーザーがログインしている場合にのみ動作するテストケースがある場合、ログインしていない状態でテストを実行するとそのテストは無意味になるため、スキップすることがあります。
  3. テストの一時的な無効化: バグが発見された場合や、テストが壊れている場合に、テストを一時的に無効化するためにテストをスキップすることがあります。その後、問題が修正されたらテストを再度有効化して再実行できます。

markTestSkippedメソッドを使用することで、テストランナーはスキップされたテストを無視し、その結果としてテスト全体の成否を判断します。これにより、テスト実行時に特定の問題が発生しても、他の有用なテストが実行されることが保証されます。また、スキップされたテストには明確なメッセージが表示されるため、問題の原因が分かりやすくなります。

テストをスキップすることは、テストケースの信頼性とテスト実行の効率を高めるために重要な手法です。

おわりに

今日は、PHPUnitでテストをスキップする方法についてご紹介しました。

本記事でご紹介したソースは、下記のリポジトリにあります。

https://github.com/Gate-Yossi/Ran/releases/tag/v2023.08.11
よっしー
よっしー

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました