ごえもん

2013.04.17

「Mockery」を使ってサクッとPHPのテストを書いてみる

ごあいさつ

はじめまして。アライドアーキテクツの石川と申します。
2月に入社してから早くも3ヶ月がたとうとしています。

私は前の職場ではほとんどjavaで開発していたのですが、
アライドに入社してからは主にPHPで開発をしています。

私の回では、その時その時に関心のある技術情報を発信していければ、と思っています。
皆様どうぞよろしくお願いいたします。

今の自分の課題はとにかくUnitテストを書くことなので、
今回はPHPのモッキングフレームワークである「Mockery」について書きたいと思います。

Mockeryって?

padraic / mockery
こちらで御座います。

static methodのモック化が出来たり、テスト対象のメソッド内部で生成されるインスタンスをモック化したり、
PHPUnitでやろうとすると一手間かかることをサクっと出来てしまいます。

Let’s インストール

Composerやgit cloneを使う方法もありますが、今回はPEARでいきます。

セットアップ

まずはMockeryのパスを通します。
その後、以下のコードをbootstrapで指定したファイルに書き、Mockeryを使用可能な状態にします。

では早速使ってみましょう

以下の様なクラスがあります。

通常これをテストする場合、先にcheckSomethingメソッドを実装したチェッカークラスが必要です。
しかし、Mockeryを使えばチェッカークラスの実装をせずにサクッとテストコードが書けちゃいます。
下の様な感じですね。

チェッカークラスの実装無しにSampleExecuterクラスのテストが書けました。
これでチェッカークラスの実装にもたついているT君を横目に自分は華麗にテストできますね!

では、下の様なケースではどうでしょう。

CheckerFactoryがdoSomethingメソッド内でnewされています。
こんな感じのコードは実際の現場では良く見かけます。

がしかし、単体テストを書く際には非常に頭を悩ますコードではないでしょうか。

これが単なるFactoryでは無くてDB接続しに行く様なクラスだった場合はその時点でハイ投了、
テストを書かずに眠れぬ夜を過ごすわけですね。これは困りました。

・・・えっ、単体テストできる?
「Mockery」を使えば、ですって・・・?

モノは試しです。サクッとテストを書いてみましょう。

なんということでしょう。
doSomethingメソッド内部で生成されるCheckerFactoryをモック化できてしまいました。
これで安心して夜も眠れます。明日も生き生きプログラミングできます。

では、下の様なケースではどうでしょうか。

で、出たー「::」。staticの大将が満を持して登場です。

これはもう終わった。涙で前が見えないリグレッションテスト地獄に突入です。
どこまでも深い闇に落ちていく感覚を貴方は覚えるでしょう。

ご安心ください!

「Mockery」はそっと救いの手を差し伸べます。

そう、そこの貴方ももうお気づきですね。
Mockeryならstaticもサクッとテストできてしまうんです。

Excellent!!
これであなたもリグレッションテスト地獄から抜け出して安らかな眠りにつくことうけあいです。

「リファクタリングしたい・・・。でも稼働しているシステムを壊すの怖いよ・・・」
「Mockery」は貴方のそんな想いにきっと応えてくれることでしょう。

注意点

「overload:」と「alias:」を使う時の注意点として。

(当然といえば当然なのですが)対象のクラス(上記例でのCheckerFactory)がロード済になっている場合はこれを使用できません。
実際のクラスがロードされる前にモック化したクラスを定義して、そいつをロードしているわけですね。

なので下の様なテストコードは通りません。

同一プロセスでは同じ名前のクラスを定義できないので、怒られてしまうんですね。

これの対処法としては、
1.phpunitのオプションにてprocess-isolationをON
2.対象メソッドに「@runInSeparateProcess」アノテーションを付与する

なんかにしとくといいと思います。パフォーマンスコストは上がっちゃいますが。

※ちなみにmakegoodではStagehand_TestRunnerがprocessIsolationに対応していない為
 エラーとなってしまうようです。
参考:makegood を試す

おわりに

長々と書いてきましたが、Mockeryは総じて使いやすいフレームワークかなと思います。

他にもパーシャルモックやメソッド呼び出し順序の指定などの機能も持っているので、
気になった方は本家のドキュメントを読んでみて下さい。

最後にアライドアーキテクツでは、一緒に単体テストしてくれるエンジニアを募集中です。
興味がある方は、こちらの採用サイトからご応募ください。