mockery

前回のブログを書いたあとに、 @hidenorigoto 先生から指摘を受けてしまったので Mockeryを紹介してみるよ。
知らなかった自分が恥ずかしいが、PHP5.3以上に対応ということも助けて、かなり高機能だよ。

パフォーマンスとかはどうかはまだ体感していないですが。

static method のモック

本シリーズで紹介している通り、static method によるテスト阻害は
なかな苦しいものです。

しかし、ロード済みでないという制約下のもとで、Mockery による
static method のモックを作ることができます。
(やはり、クラスオートロード利用向けな予感がします。)
以下が例です。


SampleSingleton クラスが、仮にDBの接続系だったりすると、それを利用している
Sample::sfoo() などのテストはやりにくくなってしまいます。

なんとかなるよ! Mockery ならね。

なんという事でしょう。これだけで、OKです。

Prefixing the valid name of a class (which is NOT currently loaded) with “alias:” will generate an “alias mock”. Alias mocks create a class alias with the given classname to stdClass and are generally used to enable the mocking of public static methods. Expectations set on the new mock object which refer to static methods will be used by all static calls to this class.

(アホ超訳)

“alias:” というのを接頭語として正しいクラス名 (まだロードされていない) を利用すると、エイリアスモックを作成します。エイリアスモックは stdClass に対象クラス名でクラスエイリアスを作成します。それは一般的に public static メソッドのモッキングに有効です。static method を参照する新しいモックオブジェクトにセットされた expectations は、そのクラスのすべての static call が呼ばれたときに使われます。

なるほどなるほど。

ちなみに、PHP5.3新関数 の class_alias() という関数を駆使しているかんじです。
今回の例では、SampleSingleton をエイリアスとして、モックのクラスを読んでいます。
で、これまた PHP5.3 の新機能である __callStatic を使って何やらムフフやっている予感がします。

パーシャルモック

Mockery は、本当にリア充なので、 JMockit でできるようなパーシャルモックもやってのけます。

上の場合、Sample::bar() メソッドだけ、モックするよーという感じです。
Sample::foo() は維持してくれます。

残念なことに、private method のモック実現は runkit 使わないと難しいそうだけど。

まだまだ、ドキュメントを読み始めたばっかりなので、
面白い使い方があったらまた紹介します。

前回の Java編に引き続きまして
今回も、テスト対象コードを変えずに、頑張ってテストを書くにはどうしたらいいのかを考えてみます。
// もちろん、リファクタリングをするべきですが、リファクタリングの足掛かりとして
// テストを先に書いておきたいという思いがあるのです。

PHPでも Mock というか、Test Double を楽しむための方法が幾つかありそうなのでまとめてみる。

オートロードが利用できるケース

symfony1.x の、 sfContext (Singletonパターン) に関わるテストで利用されている手段です。クラスの定義してあるファイルを自動的にロードするための機能spl_autoload_register() で、登録した関数は、すでにクラスが定義済みであった場合は呼ばれません。

これを利用して、全く同名のモッククラスを定義したファイルを用意しておき、テスト時に require_once などで、そのファイルを呼び出してやるわけです。これで、対象とするクラスの動きとしてはモッククラスの動きになります。

非常でお気軽な方法ですが、モック対象が頻繁に変更するようなケースなどではオススメできないかもしれません。
すべてのメソッドを網羅している必要はなく、騙すだけで良いならばこの方法はいいかもしれません。


テキトーなので、autoload.php は PSR-0 などに全然沿っておりませんのでご了承ください。 test1.php に関しては、オートロードで lib/Sample.php がロードされることはなく、先に定義した Sample クラスが利用されていることがわかります。

runkit

JMockit のように、メソッドの一部のみの挙動を変更したい!というニーズに答えるならば runkit になるかと思います。 php モジュールになってしまいますが、メソッドの内容を書き換えたり、定数を消したりとなかなか魔術を感じる便利なものです。 ただし、PHP5.3 では pecl からインストールができないので svn からソースコードを落とし、手動でコンパイルしてやる必要があります。

$ svn co https://svn.php.net/repository/pecl/runkit/trunk/ runkit
$ cd runkit
$ phpize
$ ./configure
$ make 
$ sudo make install 

以下は、クラスの定義を書き換えている様子です。

runkit + PHPMockFunction

runkit を利用して、かつ JMock のように使いやすくやろうじゃないか的なライブラリもあるのですが、
どうやらメンテされてません。誰かクールなのを作りませんか? 言いだしっぺですかそうですか。

PHPMockFunction

PHPUnit の Mock

PHPUnit の Mock は、テスト可能なコードを書いていけば使い物になりますが、レガシーなコードのテストをまずは書いて進みたいという時には適さない様に思えます。

ちなみに、Symfony2 のコンポーネントは、この機能を利用しているため、テストもコードも非常に洗練されているような気がします。

【追記】次回予告

@hidenorigoto 先生にツッコミを受けたので、続編を書きます。mockery はどこまで出来るかわからないですけど、ドキュメント見た限り、なかなかクールでした!(ってか初めて知りました。)

phpmatsuri

今年も PHPMatsuri に参加してきてしまいました。
去年は学生+ハッカソン初参加ということで、こんなにも高いお金を払っていいものか…。
ということでビクビクしながら参加ボタンを押したのを覚えていますが、
今年は、昨年の慣れもあり全力で参加ボタンを押しました。

Fabien はイケメンだった

今年も、Symfony2 周りの情報を漁りに言った。
というのも、個人としてもお仕事としても Symfony2 は使ってみたいフレームワークだったからだ。
なんと、 Fabien が来たので幾つか質問してみた。
// 僕の英語ほとんど通じませんでしたorz

1. Symfony Framework 上で使える Twig タグ(等) のドキュメントはあるか?

ない。とのことだった。チケット作るか、作っておくれ。という解答といただく。
僕がこのリストを欲しいと思った経緯は、Twig として利用できるタグ一覧は、Twig Document で見ることができるが、Symfony Framework の Bridge が追加しているタグについては一覧で見ることができないなーと思ったことが発端にある。
今のところ、全手動でリストを作ったり、Bridge のコードを見て確認していた。これは、自動化されていないし非効率。

Twig タグ一覧用の Bundle をつくろうかなー。っと思ってた矢先、Fabien はものの数時間でやってのけた。
イケメンすぎるぜ…。

Fabien の仕事スピード

こういう、質問して新たな方向性が生まれていくと、質問してすごく良かったって思いますね。

2. Sismo って version=0.99999 とかなっているけど、 1ってあるの。

なんか、version=1はありえんとか言ってたw
永遠のベータ版ですね。わかります。
でも、バージョン番号が銀河鉄道みたいな感じになっているのは面白い。

たぶん転職したとしても味わえない楽しさ

このイベントの醍醐味はなんといっても、ごった煮。ハッチポッチである。
本当にいろんな働き方をしている人がいるし、それに触れることができる。
そして、なんだかよくわからないけどトンデモなく楽しい。

今年は、こいつ↓とGarrett先生にだいぶ毒されていた可能性もあるけど。

VOYAGE GROUP の中の人がやっていた、
「今日もまた〇〇な環境で仕事をはじめるお 〜エンジニア理想の職場と私の職場〜」
という、トークでは思わず良い環境だなーーー転職したいなーーとか多少なりとも思ったけど、
たぶん、そういって転職しても絶対に味わえない楽しさが PHPMatsuri にはあると思う。

発表など

今年は、去年よりしっかりした成果物を出すことができた。

PHP Conference LT では Sismo の紹介に限ったが、今回は Hack してみようと思った。
Sismo が Symfony Component を利用しているということで、Symfony利用でLT。
次点ということでTシャツなどを頂いた!ありがとうございます。

今後は、svn対応とかもっと闇に満ちた Hack をしたいと思います。

あと、闇PHPMatsuriにも参加しました。
ドラ忍者の登場には驚きました。

ninja

PHPのマニュアルにある謎関数は、闇に満ちてます。

また来年

というわけで、最終LTはなんと40人。
参加者の大体半分が何らかの発表をしたことになります。
なかなかこういうアグレッシブで大きくてごった煮なイベントはないんじゃないでしょうか。
こんな大好きなイベントに、来年もあれば出たい。

そして、スタッフ・ゲストの皆さんと、特に僕の厄介な質問に答えてくれた Fabien と、全力でイベントを盛り上げていた参加者の皆さんに感謝したい。

Posted in PHP.