公開日:2021.10.14

【PHP】PHPunitでテストが出来ないメソッドを出来るようにする

テクログ

概要

メソッド内にある静的メソッドをラップして動的なメソッドに変更します

本題

メソッド内にデータベース(DB)のデータを取得する処理があるためにPHPunitを実行出来ないメソッドがありました。

厳密には PHPunit を実行することは出来ますが、

  • 狙ったデータでテストケースを作成したい
  • テスト用の DB を保守するのが現実的に難しい

と個人的に思っていますのでダミーデータを利用できるようにします。

PHPunit を実行出来ないメソッド例

<?php
class Sample_Class
{

    // 対象のテストしたいメソッド
    public static function test_shitai_method($arg_1)
    {
        // DBデータ取得している箇所
        // 配列で返されます
        $area_list = Db_Area::get_area_info($arg_1);

        // なにかの処理が続く
        // ...
    }

$area_list = Db_Area::get_area_info($arg_1); で DB データを配列で取得しています。

引数 $arg_1 の値によって DB から取得されるデータは変わります。このメソッドでダミーデータを利用できるようにコードを修正していきます。

メソッドを修正

既存の DB データ取得処理を内包する新しいクラスを作成する

自分でも遠回りな作業に見えますが、 PHPunit を実行できるようにするためには必要な作業だと考えています。

一気に全てのコードを変更したい気持ちもありますが、やり始めようとすると心配事が無限に湧いてくるので少しずつ対応していきます。

<?php

class Wrap_Db_Area
{
    public function get_area_info($arg_1)
    {
        return Db_Area::get_area_info($arg_1);
    }
}

引数にわたす

先程作成した class のインスタンスを引数で渡せるようにします。これはテストコードに向けた対応です。

既存の呼び出し箇所では Wrap_Db_Area インスタンスを生成せずに対象のメソッド内で行います。修正の影響を最小限に押さえるためです。

<?php
class Sample_Class
{

	// 対象のテストしたいメソッド
	public static function test_shitai_method($arg_1, $Wrap_Db_Area = null)
	{
		// 既存呼び出し箇所の影響を抑えるため
		if($Wrap_Db_Area === null)
		{
			$Wrap_Db_Area = new Wrap_Db_Area();
		}

		// DBデータ取得している箇所
		// 配列で返されます
		$area_list = $Wrap_Db_Area->get_area_info($arg_1);

		// なにかの処理が続く
		// ...
	}

ダミーデータを取得するための class を作成する

DB データではなく、ダミーデータを取得するための class およびメソッドを作成します。今回は要素が2つの配列を返します。

これで PHPunit を実行可能なテストの準備が出来ました。

<?php

class Dummy_Wrap_Db_Area
{
    public function get_area_info()
    {
        return [
            'id' => 1,
            'name' => 'tokyo',
        ];
    }
}

テストコードを作成

テストコードを作成します。狙ったデータでテストするために Dummy_Wrap_Db_Area インスタンスを生成して、対象のメソッドに渡します。
返り値は特に考えていませんでした。

<?php

use PHPUnit\Framework\TestCase;

class Tests_Sample_Class extends TestCase
{
    public function test_サンプルテスト()
    {
        $Dummy_Wrap_Db_Area = new Dummy_Wrap_Db_Area();
        $id = 1;

        // この例では test_shitai_method の引数は実質不要になっています
        // 意図しない挙動の回避のために渡しています
        $actual = Sample_Class::test_shitai_method($id, $Dummy_Wrap_Db_Area);

        $expect = 'sample'

        $this->assertEquals($expect, $actual);
    }

終わり

以上です。今回ダミーデータ取得のために作成した class の Dummy_Wrap_Db_Area はどこのディレクトリに置くのが正解なんでしょうね。テストファイルとダミーデータ取得クラスを1つのディレクトリで管理したほうが便利なんじゃないかと思っています。 他のテストのために Dummy_Wrap_Db_Area と同じようなクラスを作成していっても問題ないように感じています。

全体的に良くわかっていないですが、品質改善には繋がっていると思うのでこのまま続けようと思います。

この記事を書いた人

インドア

入社年2017年

出身地埼玉県

業務内容開発

特技または趣味映画・アニメ鑑賞、ゲーム、散歩、勉強

インドアの記事一覧へ

テクログに関する記事一覧