PHPUnit4がリリースされたのはもう3ヶ月ほど前になりますが、PHPUnit4の特徴についての日本語情報はそれほど見当たりません。そこで本記事では、Githubのリリース告知から、PHPUnit4の特徴について簡単にまとめてみました。

目次

以下では、PHPUnit4の変更点について順に説明していきます。

PHPUnit4の新機能

HHVMの対応

HHVMはFacebookがOSSとして開発を進めているPHP向けのJITコンパイラです。PHPのコードを一度専用の中間コードへと変換し、変換したコードをJITコンパイラを通して実行することにより、高速な動作を実現します。

これまでにもHHVMのコードをPHPUnitでテストするとも可能ではあったようですが、HHVMには一部独自のシンタックスを持っている点もあり、公式なサポートではなかったようです。PHPUnit4へのアップデートにより、HHVMのサポートが公式に追加されました。

テストプロキシ機能の追加

PHPUnitでモックを使用するには以下のようにします。以下はBarを検証する例です。

BarクラスのモックオブジェクトはBarがどのように定義されようと関係なくスタブとなるので、BarのdoSomethingElseの挙動を検証するには別途オブジェクトを生成してテストを記述する必要がありました。

ユニットテストであればこれで十分ですが、統合テストやエンドツーエンドテストなどのテストでは、実際のメソッドを使用したいというケースも多いでしょう。

PHPUnit4.0で追加された機能の1つが、テストプロキシと呼ばれる機構です。この機構は、元のコードの挙動自体はそのままに、エクスペクテーションを設定できるようにする機能です。この機能を実装する元となったGithubのissueには以下のように書かれています。

When writing integration tests in general and edge-to-edge tests in particular, you generally do not want to stub or mock dependencies. Sometimes, though, the ability to have expectations such as “this method has to be called with these arguments for this test to be successful” would also be useful in tests that have a larger scope than unit tests.

(雰囲気訳)統合テストや(一部の)エンドツーエンドテストでは、スタブやモックへの依存を避けたいというケースが多い。しかしこうしたテストでも「このテストはメソッドが3つの引数をとって呼ばれれば成功である」といった、エクスペクテーションが有用なケースもあるだろう。

こうした「メソッド本来の挙動はスタブに依存せず、かつエクスペクテーションを使用したい」という要求に答えるのが、このテストプロキシの機能です。上記のissueに記載されている例を見てみましょう。

このテストがパスするには、以下2つの条件を満たす必要があります。

  • Bar(のモック)はdoSomethingElseを1度だけ呼び出す → (エクスペクテーションによる検証)
  • FooのdoSomethingメソッドは、戻り値 ‘result’ を返す →(アサートによる検証)

以上のように、性質の異なる2つの検証方法を同時に扱えるのがテストプロキシの特徴です。

willReturn*()シンタックスの追加

PHPUnit4になり、新しいシンタックスも追加されています。スタブが返す値を指定する際、従来であれば、

のように、willメソッド内でreturnValueを定義する必要がありました。
PHPUnit4では、これと同等のコードを、例えば以下のように書くことができます。

多少ではありますが、これによって記述量を減らすことができるようになっています。

Strictモードにおけるカバレッジ解析機能の改善

@coversは被テスト対象のクラスやメソッドを記述するためのアノテーションです。@coverを指定した場合は、指定したメソッドのみの情報がコードカバレッジ解析の対象となります。

PHPUnit4から追加されたStrictモードでテストを実行した場合、@coversアノテーションで指定しない、想定外のコードが実行された場合にもテストが失敗するようになります。

ところが、以下のように外部からオブジェクトを使用した場合、単にテスト対象のクラスのテストを実行しているだけであるにも関わらず、Moneyのテストが実行されているとされて、失敗してしまいます。とはいえ、これはMoneyのテストケースではないため、カバレッジ解析の対象にしたくはありません。

PHPUnit4では、コードカバレッジ関連の機能にも改善が加えられています。上記のようなケースでは、@usesアノテーションを使用すると、実行はするがカバレッジ解析に含めないようにすることができます。

注意しておきたいのは、PHPDocumentorの@usesアノテーションとは同じ名前であるにも関わらず、全く異なる意味を表すという点です。PHPDocumentorで使用される@usesアノテーションはクラスレベルのアノテーションであり、一方PHPUnit4のアノテーションは関数レベルに付与するアノテーションのため、原理的には混同しないはずです。ただし、こうした2種類の意味で使用されていることは覚えておいて損はないでしょう。

@before, @after, @beforeClass, @afterClassの追加

PHPUnit3.8のドキュメントに既に記載されているため、実は3.8以降では利用可能だったようなのですが、Release Annoucementに記述されているので紹介しておきます。

テストの実行前処理・実行後処理を記述する場合、PHPUnitでは、それぞれPHPUnit_Framework_TestCaseを継承したクラスにsetUp(), tearDown()メソッドをオーバーライドして記述する仕様でした。

@before, @afterというアノテーションを使用すると、setUp()やtearDown()にこだわらずにテストの実行前処理や実行後処理を記述できるようになります。また@beforeClass, @afterClassを使用すると、実行前後に静的なメソッドを実行することができます。

Patch Coverageへの対応

PHPUnitでコードカバレッジを評価するにあたり、phpcovというツールを使用すると、複数に分けたコードカバレッジの結果をマージして評価することができます。

また単純に分割したテストケースだけでなく、変更点についてのカバレッジを確認したいこともあるでしょう。こうしたユースケースに対応して、PHPUnit4とphpcovを利用すると、Patch Coverageというパッチ単位でのカバレッジ解析を行うことができるようになりました。

まとめ

いかがでしたでしょうか?全体としてはカバレッジ解析関連の機能の改善が目立ちます。またテストプロキシの実装は、より柔軟なテストケースの記述を可能にしました。目立った新機能はありませんが、細かな部分での改善はテストの記述を多少なりとも楽にしてくれると思います。

まだ3.x系を利用している方も、PHPUnit4へアップデートして、ぜひPHPUnit4の機能を活用してみてください。