第12章 PHPUnit と Phing

Phing (PHing Is Not GNU make) は、Apache Ant をもとにしてつくられたプロジェクトビルドシステムです。 PHP の世界ではソースファイルをビルドしたりコンパイルしたりする必要はありません。 Phing が意図しているのは、パッケージの作成や配布、 そしてアプリケーションのテストを容易にすることです。 これらの作業を行うために、Phing には多くの独創的な操作モジュール ("タスク") が用意されており、 また独自のタスクを追加しやすいようにオブジェクト指向のモデルが提供されています。

Phing は PEAR インストーラでインストールできます。 コマンドラインで以下のように入力してください。

pear channel-discover pear.phing.info
pear install phing/phing

Phing ではシンプルな XML 形式のビルドファイルを使用しており、 そこで対象のツリーや実行されるタスクを指定します。 Phing に含まれる独創的なタスクのひとつに <phpunit2> タスクというものがあり、 これを使用すると PHPUnit フレームワークでテストケースを実行します。 これは、Apache Ant における JUnit タスクと同じ機能を提供するものです。

例12.1「BankAccount のテスト用の Phing build.xml ファイル」 で示しているのは、"BankAccount" という名前の <project> を指定した build.xml ファイルです。 このプロジェクトのデフォルトの <target>test となっています。<phpunit2> タスクを使用すると、*Test.php に一致するソースファイル内のすべてのテストケースを実行します。 これは <batchtest> 要素によって実現されており、 この要素は、内部の <fileset> 要素に含まれるすべてのファイルをとりまとめます。この例では、ソースファイル BankAccountTest.php に含まれるクラス BankAccountTest で宣言されているテストが実行されるわけです。

例12.1 BankAccount のテスト用の Phing build.xml ファイル

<?xml version="1.0"?>

<project name="BankAccount" basedir="." default="test">
  <target name="test">
    <phpunit2 haltonfailure="true" printsummary="true">
      <batchtest>
        <fileset dir=".">
          <include name="*Test.php"/>
        </fileset>
      </batchtest>
    </phpunit2>
  </target>
</project>


build.xml (例12.1「BankAccount のテスト用の Phing build.xml ファイル」)、 BankAccount.php (例8.3「完全な BankAccount クラス」)、 そして BankAccountTest.php (例8.1「BankAccount クラスのテスト」) が存在するディレクトリで Phing を起動すると、 プロジェクトのデフォルトのターゲットである tests にしたがってテストが行われます。

phing
Buildfile: /home/sb/build.xml

BankAccount > test:
 [phpunit2] Tests run: 4, Failures: 0, Errors: 0, Time elapsed: 0.00067 sec

BUILD FINISHED

Total time: 0.0960 seconds

<phpunit2> タスクを設定する際に使用できる パラメータの一覧を 表12.1「<phpunit2> 要素の属性」 にまとめます。

表12.1 <phpunit2> 要素の属性

名前説明デフォルト
codecoverageBooleanコードカバレッジ情報を収集します。false
haltonerrorBooleanテストの実行中にエラーが発生したら、ビルドプロセスを停止します。false
haltonfailureBooleanテストが失敗したら、ビルドプロセスを停止します。エラーも失敗と同様に扱います。false
printsummaryBoolean各テストケースについて、状態を一行で出力します。false


以下は、テストが失敗した場合の <phpunit2> タスクの出力例です。

phing
Buildfile: /home/sb/build.xml

BankAccount > test:
 [phpunit2] Tests run: 4, Failures: 1, Errors: 0, Time elapsed: 0.00067 sec
Execution of target "test" failed for the following reason:
/home/sb/build.xml:5:37: One or more tests failed

BUILD FAILED
/home/sb/build.xml:5:37: One or more tests failed
Total time: 0.0968 seconds

結果を整形する

必須要素である <batchtest> 以外にも、 <phpunit2> には別の要素を含めることができます。 <formatter> はテスト結果の出力書式を変更するために使用するものです。 usefile 属性を false にしない限り、 出力は常にファイルに送信されます。 ファイル名はフォーマッタによって事前に決められていますが、 outfile 属性を使用して変更することも可能です。 定義済みのフォーマッタには以下のようなものがあります。

brief

失敗したテストケースについての情報のみをプレーンテキストで表示します。

plain

すべてのテストケースについて、結果を一行のプレーンテキストで表示します。

xml

テストの結果を XML 形式で書き込みます。

<formatter> タスクを設定するために使用できるパラメータの一覧を 表12.2「<formatter> 要素の属性」 にまとめます。

表12.2 <formatter> 要素の属性

名前説明デフォルト
typeString定義済みのフォーマッタ (xml、plain あるいは brief) を使用します。 
classnameString独自のフォーマッタクラスの名前。 
usefileBoolean出力をファイルに送るかどうかを指定します。true
todirStringファイルを書き込むディレクトリ。 
outfileString書き込むファイル名。使用するフォーマッタに依存します。


テスト結果を HTML 形式で出力するには <phpunit2report> タスクを使用します。これは、<formatter> タスクで作成した XML ログファイルに XSLT スタイルシートを適用するものです。 Phing には phpunit2-frames.xslphpunit2-noframes.xsl の 2 種類の XSLT スタイルシートが含まれており、それぞれフレーム使用版/フレーム未使用版の HTML を生成します。

例12.2「XSLT スタイルシートを適用してテストレポートを取得する」 では、Phing で BankAccountTest クラスのテストを実行し、 XSLT スタイルシート phpunit2-frames.xsl を使用して結果を HTML 形式で得るための build.xml ファイルを示します。レポートが生成した HTML ファイルは report/ ディレクトリに保存されます。このディレクトリは prepare <target> で作成され、clean <target> で削除されます。

例12.2 XSLT スタイルシートを適用してテストレポートを取得する

<?xml version="1.0"?>

<project name="BankAccount" basedir="." default="report">
  <target name="prepare">
    <mkdir dir="report"/>
  </target>

  <target name="clean"> 
    <delete dir="report"/>
  </target>

  <target name="report" depends="prepare">
    <phpunit2>
      <batchtest>
        <fileset dir=".">
          <include name="*Test.php"/>
        </fileset>
      </batchtest>

      <formatter type="xml" todir="report" outfile="logfile.xml"/>
    </phpunit2>

    <phpunit2report infile="report/logfile.xml"
                    styledir="/usr/lib/php/data/phing/etc"
                    format="frames"
                    todir="report"/>
  </target>
</project>


以下に、phing コマンドを実行した際の出力例を示します。

phing
Buildfile: /home/sb/build.xml

BankAccount > prepare:
    [mkdir] Created dir: /home/sb/report

BankAccount > report:

BUILD FINISHED

Total time: 0.1112 seconds

生成されたテストレポートのタイトルページは 図12.1「生成されたテストレポート」 のようになります。

図12.1 生成されたテストレポート

生成されたテストレポート


<phpunit2report> タスクを設定するために使用できるパラメータの一覧を 表12.3「<phpunit2report> 要素の属性」 にまとめます。

表12.3 <phpunit2report> 要素の属性

名前説明デフォルト
infileString使用する XML 結果ファイル名。testsuites.xml
formatString生成される結果の書式。frames あるいは noframes のいずれかでなければなりません。noframes
styledirStringスタイルシートの存在する場所。スタイルシートは、以下の規約を満たすものでなければなりません。frames フォーマット用のスタイルシートの名前は phpunit2-frames.xsl であること。また、noframes フォーマット用のスタイルシートの名前は phpunit2-noframes.xsl であること。 
todirString変換後のファイルを書き込むディレクトリ。 


いま作成したテストレポートのほかに、 Phing ではコードカバレッジレポートを作成することもできます。そのためには、 <coverage-setup> タスクおよび <coverage-report> タスクを使用します。 前者はテストの実行中にコードカバレッジ情報を保存するためのデータベースを準備するタスクで、 後者は XSLT スタイルシートを使用して結果を HTML 形式に変換するタスクです。

例12.3「コードカバレッジレポートの生成」 では、 Phing で BankAccountTest クラスのテストを実行し、 HTML 形式のコードカバレッジレポートを生成するための build.xml ファイルを示します。

例12.3 コードカバレッジレポートの生成

<?xml version="1.0"?>

<project name="BankAccount" basedir="." default="coverage-report">
  <target name="prepare">
    <mkdir dir="coverage-report"/>
  </target>

  <target name="clean"> 
    <delete dir="coverage-report"/>
  </target>

  <target name="coverage-report" depends="prepare">
    <coverage-setup database="./coverage-report/database">
      <fileset dir=".">
        <include name="*.php"/>
        <exclude name="*Test.php"/>
      </fileset>
    </coverage-setup>

    <phpunit2 codecoverage="true">
      <batchtest>
        <fileset dir=".">
          <include name="*Test.php"/>
        </fileset>
      </batchtest>
    </phpunit2>

    <coverage-report outfile="coverage-report/coverage.xml">
      <report styledir="/usr/lib/php/data/phing/etc"
              todir="coverage-report"/>
    </coverage-report>
  </target>
</project>


生成されたコードカバレッジレポートのタイトルページは 図12.2「生成されたコードカバレッジレポート」 のようになります。

図12.2 生成されたコードカバレッジレポート

生成されたコードカバレッジレポート