PHPUnitでPrivateメソッドの単体テスト

2010年3月18日 加藤 雄亮 このエントリーをはてなブックマークに追加 Clip to Evernote

皆さん、単体テストしてますか??
PHPで単体テストを実施する場合、私はPHPUnitを使用します。コーディングの時間が無く、テストを書けない時もありますが、出来ればTDD(テスト駆動開発)を実践したいですよね。

さて、今回はPHPUnitでPrivateやProtectedなどのアクセス権を設定したメソッドのテストコードについてです。

プライベートメソッドに対するテスト方法で紹介されているような方法もあると思いますが、ここではもっと簡単なテスト方法をご紹介します。

テスト対象のクラス

あまり良い例ではありませんが、ここでは単純にBMIを計算するBmiクラスを作成しました。PublicメソッドとProtectedメソッドの2つのメソッドが存在します。
<?php
class Bmi
{
    public function getBmi($height, $weight)
    {
        $height = $this->_convertHeight($height);

        return round($weight / ($height * $height), 1);
    }

    protected function _convertHeight($height)
    {
        return $height / 100;
    }
}
?>


テストを実施するクラス

通常のままだとProtectedメソッドのテストが行えないため、Bmiクラスを継承したBmiExtendedクラスを作成し、ProtectedメソッドをラップしたPublicメソッドを作成します。
テストコード内では、Bmiクラスでは無く、BmiExtendedクラスを使用してテストを行います。
<?php
require_once 'PHPUnit/Framework.php';
require_once 'Bmi.php';

class BmiTest extends PHPUnit_Framework_TestCase
{
    protected $_bmi;

    protected function setUp()
    {
        $this->_bmi = new BmiExtended();
    }

    public function testGetBmi()
    {
        $this->assertEquals(24.2, $this->_bmi->getBmi(170, 70));
    }

    public function testConvertHeight()
    {
        $this->assertEquals(1.7, $this->_bmi->convertHeight(170));
    }
}

class BmiExtended extends Bmi
{
    public function convertHeight($height)
    {
        return parent::_convertHeight($height);
    }
}
?>


単体テスト実施

[user@www ~]$ phpunit BmiTest.php
PHPUnit 3.4.11 by Sebastian Bergmann.

..

Time: 0 seconds, Memory: 3.50Mb

OK (2 tests, 2 assertions)


このようにテストを実施するクラスのファイル内にテスト対象のサブクラスを作成すれば、簡単にPublicメソッド以外のアクセス権を持ったメソッドのテストが出来ます。

テスト時にアクセス権を書き換えている場合や、不要なPublicメソッドを作成している場合、Publicメソッド内でPrivateメソッドの命令が網羅されているか不安な場合など、この方法なら簡単にテストを実施する事ができますので、お試しあれ。