Technote

by sizuhiko

PHP Matsuri2012を終えて 〜 Retrospective of PHP Matsuri 2012 in Fukuoka

<!– more –>
On this year, PHP Matsuri had convened of 3rd time around.
The participant who first timer and the repeater are split 50:50.
It become common composition of the participant in the event of 100 person scale.

As a motive of participation are followings:
1. Repeater brings the friend of the first participation.
2. Participant in the vicinity who saw last year’s article
3. Enthusiastic fan

I think that PHP Matsuri has become a annual event at late autumn.

As the PHP Matsuri staff, this maybe first post. So I stop it only in an easy summary.
To be continues and the details are posted by DANCHO.

PHP Matsuriも3回目の開催となりました。
参加者は、始めての人が半分ぐらい、リピーターが半分ぐらいで、100人規模のイベントでは良くある人数構成になってきました。
参加の動機としては、
1. リピーターの人が初参加の友人を連れてくる
2. 去年の記事を見た、近隣の参加者
3. 熱狂的ファン
があると思っています。

そういう意味でPHP Matsuriは晩秋の恒例行事となってきたのではないかと思います。

PHP Matsuri 青年団の最初をきって書くので、簡単なまとめだけに留めたいと思います。詳しくは団長が…..

Thanks:


It had been offered by many sponsors from the enterprise to the individual.
As a result, a very gorgeous prize was able to be prepared. And, it became a very happy event.
I’m really thankful.

感謝:
今年は、企業から個人まで多くのスポンサー様にご提供いただき、大変豪華な賞品を用意でき、とても楽しいイベントになりました。本当に感謝しております。

This year’s challenge:

The 1st time and the 2nd times were the same hotel groups.
It is easy to have done arrangements and the preparation about the hall.
However, this year of the third times was a hall of “Fukuoka Prefecture Ruby and contents industry promotion center” that a public organization manages .
(The hotel prepared it until last year. )Because the task had increased, the staff became busy.
However, the registration fee became low price, and the prize of LT became gorgeous.

今年のチャレンジ:
1回目、2回目とも同じ系列のホテルだったこともあり、会場に関する手配や準備はとてもやりやすかったです。3回目の今年は「福岡県Ruby・コンテンツ産業振興センター」という公的な機関が運営する会場でした。ホテルの人が担当してくれていた雑務をスタッフ主導でやることは大変でしたが、その分参加費が安くなったりLTの賞品が豪華になったことで参加者へ還元できたのではないかと思っています。

This is good:


It is some the improved points that it is a few problem until last year
1. The wifi doesn’t disconnect. We think that we solved the problem of the network because we have controlled the connection with 3 access point.
2. Just good temperature.
There were some comments that it was cold, too. However, I think the improvement to have been done since last year (Because the hall is too wide and air-conditioning was not effective).
3. Neither the conference nor the workshop get entangled. it became a concentrating workshop by using another conference room.

特に良かった事:
昨年までちょっと課題だと思っていた部分で、いくつか改善された点ですが
1. 無線が切れない。うまく分散することで、ネットワークの問題はなかったと思います
2. ちょうど良い温度。若干寒いというご意見もありましたが、昨年は会場が広すぎて空調が効かなかったりしたので、改善はされていたと思います
3. 講演とワークショップが混線しない。会議室が別だったこともあり、ワークショップを集中して開催できたと思います

Important things :


These are important thing in the event. I think that I was able to do this this year.
1. We are nice smile
2. It doesn’t become loneliness. If first timer that there was not a friend either, then I think that they were able to exchange it at the ice break and break-time.
3. Meal is delicious.
4. Wanna become repeater. I think this to be feelings that each one was able to take home.

イベントで大事な事:
私がイベント大事だと思っていることで、今年も実践できていたと思います
1. みんな笑顔
2. ボッチを作らない。もちろん始めての参加で友人もいなかったという人もいると思いますが、アイスブレークや食事時間に交流できたと思います
3. 食事が美味しい
4. また参加したくなる。これは参加者皆さんが持ち帰っていただけた気持ちと期待しています

At last, My presentation:


In this year, I had plan to make demonstrate application look like the micro framework with using followings component:

The demonstration was not complete.
When the sample application program became runnable a little more well, I want to announce in Blog or the PHP study meet up.

最後に私事:
今年は以下のどちらかを使って、マイクロフレームワーク的なコードが書けるところをデモする予定でした。

で、結局 Respectのバグっぽい箇所をふんでしまって、朝方6時ぐらいに Rails Routerに切り替えたけど、こっちはこっちでうまく動作しなくて、8時ぐらいに元鞘に。うまく動いている箇所だけで発表しました。
これらは、もうちょっとうまく動くサンプルアプリが作れたら、BlogやPHP勉強会などで発表したいと思います。

See you PHP Matsuri 2013 (maybe HOKKAIDO) !!

また来年のPHP Matsuri(たぶん北海道)で会いましょう

CakePHP2 実践入門 が出ます

<!– more –>

表題のとおりCakePHP2.x系をターゲットにした本がいよいよ9/29に発売となります(池袋ジュンク堂では本日より10冊の先行発売があった模様です)。

本書のほとんどを企画の安藤さんが書いたのですが、わたしも共著のメンバーとして10章 プラグイン、11章 コンソール、12章 ユニットテスト を担当しました。

本書のオススメ・ポイント

執筆の一員という立場で手前味噌なのですが、まだポチっとしていない方の背中を押すという意味で、5つ紹介します。

  • 豪華な執筆陣
  • 最新のバージョン2.2への追従
  • よりチェックされた本文とサンプルコード
  • 便利なチートシート付き
  • 隠れポイント

豪華な執筆陣

本の帯にも書かれている「コミュニティ主要メンバーが最前線のノウハウを凝縮」という部分に現れているとおり、著者それぞれはCakePHPの勉強会や、翻訳、本体へのパッチ送付、Blogなどで勢力的に活動しており、得意な分野について担当するという意味では共著のメリットを最大限に活かした本と言えます。

そういう意味で各章には、これまでのCakePHP本にはなかったTipsが含まれていると思います。「実践入門」というタイトルですが、現在CakePHPを使っている方にも何か新しい気付きがあると良いなと思っています。

最新のバージョン2.2への追従

本書の始まりはCakePHP2.0の頃であり、「もしかしたら発売する頃には2.1になっているかもね」と言われていたものです。それが気付くと2.1はリリースになり、まだ2.2はリリースとは遠いところにある存在でした。2.1に対応した内容がほぼFixしたころに、2.2が驚く程の速さでリリース(ほんとの直前には2.2.1)となりさらに追従というようなサイクルでした。もちろん本書を手に取っていただけるとわかるのですが、数カ所「このバージョンでは・・・」という記述が見られるようにバージョン違いによる説明が含まれているのも特徴です。

よりチェックされた本文とサンプルコード

今まで何度か執筆に参加したのですが、今回は期間も内容もかなりタフなものだったと思います。それはバージョン追従の問題だったり、なるべく多くの内容を詰め込みたいがページ数には上限があり内容を精査したりといったことです。そんな中でも技評の担当者の方が、本の全体を通しての統一感といったところに細かくチェックしてくれていて、共著にありがちなバラバラ感が少なく通して読んだときの違和感もないと思います。また最新バージョンでサンプルコードの動作確認を都度してくれた(これは今までにない経験)ので、サンプルコードを実際に動かして試してみたいという人にも、ここ動かないなぁという迷いが少ないと思います(もちろん著者もチェックしているつもりなのですが、内容の改変などにコード部分が追いついていないということもまま・・・汗)。

便利なチートシート

巻末の30ページに渡り記述されているチートシートは本当に便利で、これは現在CakePHPで開発している人にもとても役立つものになっていると思います。これだけでも本書を手元に置く価値があるかも?!

隠れポイント

最後にお気に入りポイントを1つ。

本のカバーを外すと裏表紙にCakePHPの公式マークがプリントされています。ぜひチェックしてみてください。

さいごに

さて執筆陣も6名となり、本のサインをコンプリートしたいと思う人にはかなり難しい状況と思います。ところが、それが叶う可能性が11/3,11/4にありますよ(という宣伝)。

11/3,11/4にPHP Matsuri 2012が福岡にて開催されます。

http://www.phpmatsuri.net/2012/

このイベントの青年団がページの下にアイコン表示されていますが、なんと著者6名全員が青年団!!

つまりMatsuriに参加するとサインがコンプリートすると思いますので、今すぐサイトからチケットを申し込みましょう(数に限りがあります)。個人スポンサーもお待ちしています。

CakeFest2012で発表&参加しました

<!– more –>

今年もBakerの祭典CakeFestが(昨年と同じ)マンチェスターで開催されました。

今年はCFPが通ってスピーカーとして参加することになり、だいぶ準備に時間をかけて….と思ったら実質2週間ぐらい前に夏休みの宿題状態で片付けたのでした。。。

CakeFestのカンファレンスは9/1と9/2の2日間で行われたのですが、私は休暇(30,31の)も含め8/29夜からマンチェスター入りをしていました。 ヒースローの乗り継ぎ(五輪効果で綺麗になっていた)や空港からの鉄道や徒歩など慣れたもので、飛行機や鉄道が遅れるという英国定番のトラブル(でもないらしい)で疲れての到着となりました。

カンファレンス1日目

簡単に1日目に参加したセッションをふりかえっておきます。

09:00 - 09:25 Keynote: CakeFest 2012 Introduction

これは本来グラハムがやる予定だったのですが、 急遽家庭の事情で来れなくなったので、最初のセッションがスキップされるかと心配された。時間になっても始まらないし、特に説明はないのだけれど、まぁCakeのコミュニティっぽいと言えばそうかなと思ったら、9:20になってマークが壇上に上がってなんとかキーノートを開始。

  • 今年は10カ国以上から参加者がいる。世界的に興味を持たれている
  • 2日間のワークショップと2日間のカンファレンス。2トラック、ライブストリーミングなど見どころがたくさん

実はマークとグラハムはSkypeでやろうと思ったけど、うまくつながらなかったというのを休憩時間に聞きました。

09:25 - 09:40 Keynote: Hell has Frozen Over

  • マイクロソフトのスポンサーセッション
  • 99.95% SLA
  • Linux,Mac,Windowsに対応したツールがある
  • 言語はASP.NETかNode.jsかPHP
  • FTPかGitでデプロイできる
  • 始めは無料だよ
  • サーバを作るときはリージョンとDBが選べる。MySQLが使えるよ
  • Gitリポジトリを設定して、ダウンロードできるよ
  • sharedインスタンスと、reserved(専用)インスタンスみたいなのがあって良いよ。最初sharedでresercedに移動も可能
  • ロードバランサでどこかが止まっても違うインスタンスに自動的に再デプロイされる
  • ビッグデータ、データベース、NoSQLストレージ、最適なネットワーク、キャッシュ(Memcacheとかね)、メッセージングなど使えるよ
  • 3ヶ月は無料
  • 詳しくは彼に聞いてね(午後のセッションをやる技術者らしい)、てきな振りで終わり w

09:40 - 10:30 Keynote: Making the most of 2.2

コアデベロッパーの中心人物であるマークとホセのセッション

ViewブロックがDRYじゃなくてなんとかしたかった

  • Jinja/Twigから影響を受けたよ
  • slots/blocksレイアウトがテンプレートで使える

JSONとかXMLとか面倒だった

  • _serializeというset名でビューに特別に使えるようにしたお

Setの問題があったね

  • Set::extractはいいけど、遅いよ
  • いくつかのxpathには対応していなかったし、解決できない問題もあった。内部はクレイジーだったぜ
  • ハッシュにして1.6倍ぐらい速くなったよ
  • ハッシュはsetの90%ぐらいが実装されている

CakeTimeとCakeNumberの問題があったね

  • HelperじゃなくてUtilライブラリで良いよね。HTML以外でも使うし
  • 良くテストされた datetimeを使っているよ

ロギングは特に問題だったね

  • pythonのscopesからアイデアをもらったよ
  • Configで設定すればmongoとかにもストアできる

イベント

  • いろんなところで使えるイベントシステム
  • いろいろとイベントが使えるようになっているよ
  • コールバックを使って簡単にできるよ
  • 独自イベントも簡単!

キャッシュ

  • assetコンパイルを使うと、部品をキャッシュできるよ
  • beforedispacherとかafterdispacherとか使うといいよ
  • Responseオブジェクトを使って設定するよ

キャッシュグループ

  • 何それ?
  • キャッシュに論理的なグループを作れるよ
  • 動的にはできないから、自分のstrategyで計画しなくちゃ行けない

バリデーション

  • 動的に追加、変更、削除できるようになったよ

11:00 - 11:30 Lightning Strikes from Windows Azure

ここから2トラックになる。 マイクロソフトのスポンサーセッションで技術担当のCoryによるテクニカルセッション

  • Macでも開発できるよ(ここ強調しているな)
  • 数クリックで開始できるよ
  • スケールを簡単に管理できるよ
  • 自動的にロードバランスするし、インスタンスを超えてストレージは共有される

Hello Worldのデモ

  • Macだぜ
  • azure site でオプションがいっぱい出る
  • azure site create ‘cf-cakegest’ –git
  • git add/commit/push
  • azureの管理画面で cf-cakefestが出ている
  • azure site browse – ブラウザが立ち上がった
  • pushすると自動的にdeployment historyがpushされているように見える
  • azure site deployment list – 一覧が見える
  • azure site deployment redeploy 'コミットID’
  • モニターでいろいろチェックして(404の数とか)追加で見れる
  • VMのOS選択はいろいろ選べるよ。もちろんLinuxも
  • azure vm コマンド使うよ
  • azure vm create -h とか
  • azure vm create 'name’ 'vm’ 'user’ 'password’ -l 'リージョン’
  • composerやgithubが使えるぜー

11:30 - 12:30 Create a RESTfull api

@ceeramのほうのマークによるセッション。

RESTとはの基本にとても時間をかけて説明していた(重要)。基本からPATCH、HATEOASまで全部入りだった。その後CakePHPでの適用方法について

router に追加するぞ

  • Router::parseExtensions(); // all
  • Router::parseExtensions('json’); // only json

RequestHandlerコンポーネント使うよ

  • viewClassMapを使うと変えられるよ
  • 'RequestHandler’=>array('viewClassMap’=>array('json’=>'RestJson’,'xml’=>'RestXml’))) とか

その他

  • 2.x からは _serialize を使って set すれば良いよ
  • 見つからなかったら NotFoundException とか
  • Router::mapResources(array('Cats’, 'Users’))とか使うとマップできるよ
  • APacheとかでPUTやDELETEを許可しておく必要があるよね
  • Router::resourceMap(array(array('action' => update','method'=>'PATCH'. 'id'=>true) みたいに書くといいよね
  • Router::mapResources(array('Cats’, 'USers’, 'Pizza.Orders’),array('prefix’=>’/api’) とか書くといいよ
  • Router::connect('url’, action… ) とかでもOK
  • CakeRequest::addDetector('patch’, array('env’=>'REQUEST_METHOD’, 'value’=>'PATCH’)); なんて書き方もできるよ(知らなかった)
  • CakeResponse 使ってね
  • 認証もいろいろサポート
  • Versioningが重要だよ

12:30 - 13:30 Lunch

カンファレンスに来たらランチが美味しいことはとても重要だと感じました。今年は本当においしかった!!

Random tips that will save your projects life

マリアーノのセッション。毎年興味深いセッションである。 内容はとにかく広範囲にわたっていて、

  • Git使えやー
  • Monitだろー
  • サーバ監視しろやー
  • PHPログはトラックした方がいいよね
  • Duckesboard
  • statsdとか
  • Google Analyticsもいいよね
  • やっぱ Varnishだよね
  • PHP -> Redis pub/sub -> Node.js -> soket.io -> Client でいいよね
  • Sphinx はスケーラビリティがあるし、PECLかSQL使えるし、リアルタイムインデックスだしいいよね

みたいな感じ。

How to make your CakePHP website into a Phone app

ここでは安藤さんのセッションの裏で、関西弁こてこてのリチャードさんによるセッションに参加。

  • PhoneGap では WebView を使ってappっぽく見せた
  • Zendで作ったけどね(笑)
  • 2,231,400 のユニークユーザを捌いたぜ。さすがBBC&オリンピック
  • 15,000,000 ページビュー/日だったぜ

その後

コアチームによるQ&Aセッションがあり、 いろいろ興味深いトークが繰り広げられました。

さらにLTがありの流れでビアタイムに。LTは発表者が何度もやったり、スライドはない方が多かったりドラはなかったり(まぁ当然か)、なんか日本のLTに慣れているとフワフワ感がたまりませんな(笑)

急遽#CakeRadioGaGaをGoogle+でやることになり、日本時間は日曜日の2時ぐらいだったのかな?ゲリラだったのに数名の閲覧者が見てくれました。

カンファレンス2日目

今日は発表日なのでなんか寝付きが悪くて、何度も目を覚ます事に。。。

09:00 - 10:00 Simple search with elastic search

2日目は最初から2トラックで。メイン会場はマークによりelastic seachのセッション。いわゆる検索エンジンで、よくApache Solrと比較されるやつ。マークのセッションはとてもわかりやすく、Cakeからのインテグレーション方法もよくわかった。これはスライドを見た方が良いね。

10:00 - 10:30 BDD for CakePHP applications

さて私のセッションですが、Twitterでの感想はなかなか好評だったみたいで、助かりました。マークからもランチのときにコメントをもらえたし。

トラブルが2つあって、

  • セッション中にレンタルしていた3G Wifiが死亡して、急遽ホテルのWifiへ切り替え。デモの最中に慌ててしまった
  • セッションのコンテンツ(英文)をDropboxに入れて、AndroidのMarkdownビューワーで見ながら話していたけど、Androidの自動回転がONのままで頻繁に回転が起きてしまう自体に。そうするとページTOPまでスクロールして、見直したら位置がおかしくなってアワアワしてしまった。自動回転はオフにしておかないとね。後半は記憶に頼って話しました。

で、ネタとしては、BDDのBはBeerだよね、というのは今年も鉄板でこれは世界中で通じる良い導入になります。それとマンチェスターなので香川ですな。和みました。

その後

なぜかここからざっくりとしたまとめになりますが、あまりCakeと直結する話題が少なくなったので、軽く。

  • あのYour code sucks, let’s fix itのRafaelによるセッションが。彼は現在アムステルダムに住んでいて、発表の内容からするとSymfonyガイなのかもしれないなと思いました。Composerの発表もしていたし。
  • 再びmackstarさんのセッションで、Backbone.js。これはCakeと直結しているのですが、まぁmackstarさんのgithubをチェックしましょう。Ember.jsについてはまだPHP界隈では使われていないし知っている人も少ないからBackbone.jsが良いねという話でした。
  • グラハムがやる予定だったFablicのセッションをマークが。ちょうど新原さんがTwitterでFablicについてつぶやいたのでストリーミング見ているのかと思ったら偶然だったらしく、びっくりしました

で、この後 PechaKuchaトークをやるまでの間に #CakeRadioGaGaの生放送を再び。日本では明日は月曜日なので早めの時間に。

この間にやっぱり結構帰る人がいて、さらに戻ってみるとラリーが機材を撤去していたり、何だろうと思ったら応募者がいなかったらしい。まぁLTでだいぶ発表があったのでそんなもんかなと。あとグラハムがいなくてイベントの仕切りが終始ふわふわしていたのも影響しているみたいでした。

もちろん定番のリアルケーキも出ましたよ。大きいものはホテルでは作れないということで、小さいものが7周年を記念して7つになったということでした。ランチデザートで出て、各テーブルに配られて行きました。そういえばケーキの前でのコアデベロッパー写真とか、全体の集合写真とかなかったなー えっ?レポートが段々尻すぼみだって?。いや、実際イベント全体のテンションもそんな感じで。。。。察してください www

まとめ

良かった事、反省点、いろいろあるけど、悪い事はないのでみんな海外のカンファレンスも出るといいね。もちろん発表することが重要で、ボクみたいにあんまり英会話得意じゃないけど発表すれば声もかけてもらえるし、プラグインや発表資料をチェックしてくれたりするので、それでフォローできればOKと思っています。

来年(こそ?)は、カルフォルニアらしいのでマンチェスターより行きやすい!。みんなで参加しよう!!

BDD Plugin for CakePHP2を公開しました

<!– more –>

BDD Plugin for CakePHP (https://github.com/sizuhiko/Bdd) はCakePHPからRuby on Railsのように2つのBDDフレームワークを実行できるようにするインテグレーション・プラグインです。
2つのBDDフレームワークは

  • スペック・フレームワークは Spec for PHP
  • ストーリー・フレームワークは Behat を利用しています。
    それぞれのフレームワークの特徴は、共に外側のインターフェースを自然言語で記述できることでコミュニケーション・ツールとしての役割を持っています。

BehatをCakePHPから利用するためのプラグインとしてCakeBehatを公開してきました。
そういう意味で、これはCakeBehatの改良版と言って間違いありません。
CakeBehatからの進化ポイントは以下のとおりです。

  • スペックフレームワーク Spec for PHP を実行可能に
  • 依存関係の解決に Composer を利用

詳しくは github のREADMEで書いているのですが、英語(あっているか不安がたっぷりですが)で書いてあるので、安心の日本語で解説したいと思います。
今回はサンプルアプリケーション BddExampleApp (https://github.com/sizuhiko/BddExampleApp) に簡単なチュートリアルを書いているので、こちらの流れを中心に説明していきます。

インストール

  • CakePHP2 をインストール (2.2以降を推奨)
  • PHPUnit をインストール(pearなどを利用)
  • git cloneを使うかgithubのサイトからサンプルアプリケーションBddExampleAppをCakePHPのルートディレクトリに展開。このとき app, feature, spec ディレクトリが必要になります。
  • テストデータを投入するのにfixture以外の仕組みとして fixture-factory(https://github.com/rodrigorm/fixture-factory) を使っています。リンク先の installation を参考にインストールして欲しいのですが、ディレクトリ名が解決できない問題(?)があるのでvendorsディレクトリをvendorにリネームしてください。

    $ mv app/Plugin/fixturefactory/vendors app/Plugin/fixturefactory/vendor

  • データベースを作成して、テーブルを作成してください。データベースはテスト用、開発用の2つが必要で、その両方に app/Config/sql/posts_ja.sql のSQLを実行してください。

  • 環境設定ファイル app/Config/core.php と database.php を環境に合わせて変更してください。database.phpのデータベース名やログイン、パスワードなどは前項で設定した値に変更してください。またブラウザ経由のテストでテスト用データベースを参照するために test.localhost のようなテスト時のホスト名が必要なので、そのままhostsに設定するか違う名前に変更してください。

  • BDDプラグインをインストールします。CakePHPのプラグインディレクトリ (/plugins)  に移動して git clone するか、githubのサイトからダウンロードして展開してください。

  • そうすると /plugings/Bdd のようなディレクトリ階層になるので、その /plugings/Bdd に移動してください。Composerをインストールして依存関係を解決します。

    curl -s https://getcomposer.org/installer | php php composer.phar install –dev

  • 最後にbehatが利用するテスト用URLを設定します。app/Config/behat.ymlの設定値はひとまず「base_url: ’http://test.localhost:8888/bdd/‘」のようになっているので、実際にインストールしたアクセス可能なURLに変更してください。このときdatabase.phpで設定したテスト用のホスト名になってることが重要です。

インストールが完了したら、http://localhost:8888/bdd/posts/ にアクセスして3件のリストが表示されていれば大丈夫です。

テストを実行してみる

CakePHPのルートディレクトリに移動して以下のようにコマンドを実行します。behatのテストでseleniumを利用しているので、可能であればコチラ(http://www.phpunit.de/manual/3.6/ja/selenium.html)を参考にseleniumをダウンロードして実行しておいてください。

$ lib/Cake/Console/cake Bdd.spec

Welcome to CakePHP v2.x.x Console
---------------------------------------------------------------
App : app
Path: /your CakePHP root/app/
---------------------------------------------------------------
•••••••••••••••••••••••••••••••••••••••••••••••••
▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
✔ OK ❯ Passed 49 of 49 (0.17s 22Mb)
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔

$ lib/Cake/Console/cake Bdd.story

Welcome to CakePHP v2.x.x Console
---------------------------------------------------------------
App : app
Path: /your CakePHP root/app/
---------------------------------------------------------------
Feature:
  In order to tell the masses what's on my mind
  As a user
  I want to read articles on the site

  Background:              # /your CakePHP root/features/posts.feature:7
    Given there is a post: # /your CakePHP root/features/steps/posts_step.php:3
      | Title              | Body                          |
      | The title          | This is the post body.        |
      | A title once again | And the post body follows.    |
      | Title strikes back | This is really exciting! Not. |

  Scenario: Show articles                 # /your CakePHP root/features/posts.feature:14
    When I am on "TopPage"                # FeatureContext::visit()
    Then I should see "The title"         # FeatureContext::assertPageContainsText()
    And I should see "A title once again" # FeatureContext::assertPageContainsText()
    And I should see "Title strikes back" # FeatureContext::assertPageContainsText()

....

スペックフレームワークの使い方

基本的なコマンドラインのオプションなどはSpec for PHP(https://github.com/drslump/Spec-PHP) に対して透過的になっていて、意味もPHPUnitと似ている(実際内部はPHPUnitである)ので、感覚は掴みやすいと思います。
前のコマンド実行例では Bdd.spec にオプションがない状況でしたが、代表的な使い方は以下のとおりです。

# デフォルトディレクトリ(spec)にあるspecファイルをすべて実行
lib/Cake/Console/cake Bdd.spec

# 指定したディレクトリ(spec)にあるspecファイルをすべて実行
lib/Cake/Console/cake Bdd.spec spec

# 指定したファイルだけを実行
lib/Cake/Console/cake Bdd.spec spec/post.spec.php

# オプションの詳細を見る
lib/Cake/Console/cake Bdd.spec --help

スペックファイルの命名ルールは以下のようにspec.phpで終わる3通りです。

  • post.spec.php
  • post_spec.php
  • PostSpec.php

モデルをテストする

モデルをテストするためにCakeTestCaseを継承したCakeSpecというPHPUnitのテストケースを用意しています。これを classアノテーションで指定します。

あとはフィクスチャですが、これはCake本来のテストで利用するものと同じで、宣言する場所と意味がちょっと変わってきます。
Cakeのユニットテストでは、テストケースクラスのメンバ変数として$fixuresを宣言するのですが、スペックでは$W(ワールド)インスタンスのfixtures変数にセットします。arrayの書き方は同じです。ただしスペックコードではitブロックの度にfixturesが解決されるのでitの前のbeforeやbefore_eachブロックで書いておけば1ファイル中に何度出て来ても問題ありません。ちょうどloadFixtures()のような動きなのですが、この場合もCakeTestCaseではfixturesにテストケース内で利用するすべてのフィクスチャを書いておく必要がありますが、スペックでは下位階層で利用する分だけでOKです。これはスペックコードのスコープによることろなのですが、これを詳しく知るには、Spec for PHPがどのようにDSLで解釈してPHPコードをPHPUnitに実行させるかを見た方が良いでしょう。

# スペックコードをPHPコードに変換して出力
$ lib/Cake/Console/Bdd.spec spec/post.spec.php --dump

Spec for PHP はPHPUnitのTestSuiteとTestCaseを利用しています。このうちitブロックがTestCaseに該当します。その他のdescribe、contextやbeforeはTestSuiteになっています。つまりitブロックで $this 変数を使うと TestCase のインスタンスになります。それ以外のbeforeなどは実際にはTestSuiteにマッピングされるので、実行中のテストケースインスタンスを取得したい場合は DrSlumpSpec::test() を呼び出す事で利用可能になります。このスコープが重要になってくるのが、次のコントローラのテストです。

コントローラをテストする

コントローラをテストするためにControllerTestCaseを継承したControllerSpecというPHPUnitのテストケースを用意しています。モデルと同様にclassアノテーションで指定します。ControllerTestCaseを継承しているのでもちろんtestAction()が利用可能なのですが、ここで重要になるのが、スコープです。it以外でtestActionはControllerTestCase($this)から呼び出せないので、DrSlumpSpec::test()->testAction のように記述します。fixturesに関してはモデルと同じく下位階層に対して有効になります。

Spec for PHPを使いこなすには

Spec for PHPの評価(マッチング)はHamcrestを利用しているので自然言語で書く事が可能です。私はPHPUnitのassertXXXXXを覚えるよりも直感的で、こう書いたらできそう(実際できる!!)というのが良いと思っています。
どんな書き方があるかは、サンプルアプリケーションの spec 下に post 以外のテストコードも使い方例として入れてあるので、それを読むとわかるのではないかと思います。

ストーリーフレームワークを利用する

こちらもスペックと同じく基本的なコマンドラインのオプションなどはBehat(http://behat.org/) に対して透過的になっているので、詳しくは公式のドキュメントかhelpで見るのが良いでしょう。
先のコマンド実行例では Bdd.stoy にオプションがない状況でしたが、代表的な使い方は以下のとおりです。

# デフォルトディレクトリ(features)にあるfeatureファイルをすべて実行
lib/Cake/Console/cake Bdd.story

# 指定されたfeatureファイルを実行
lib/Cake/Console/cake Bdd.story features/posts_ja.feature

# より詳しいヘルプを見る
lib/Cake/Console/cake Bdd.story --help

これ以外に関していえばCakeBehatと基本的な仕組みは変わっていません。

フィーチャーを書く

公式ドキュメントの “Define your Feature in Quick Intro to Behat” : http://docs.behat.org/quick_intro.html#define-your-feature を見ると良いかな….(手抜きですみません)

実際のサンプルには日本語記述も入っています。

ステップを書く

これも公式ドキュメント(See “Writing your Step definitions in Quick Intro to Behat” : http://docs.behat.org/quick_intro.html#writing-your-step-definitions)を読むといいね、ってことなんですが、Behatのドキュメントで最初に出会えるステップの書き方は、FeatureContextにステップを追加していく書き方です。これだと独自ステップが少ないうちは良いのですが、増えて来たら分割するのか、どういう単位で分割するのか、そのままビッククラスにするのか…という分岐点にたたされます。
それぐらいなら最初から分けておこうということで、例えばフィーチャの単位であったり自分たちで決めたルールでステップファイルを分割できる方式にしておきましょう。Behatではクロージャ定義も可能なので http://docs.behat.org/guides/5.closures.html の書き方に従って書いてみましょう。サンプルアプリケーションもこの流れに沿っています。
基本的にステップをstepディレクトリ以下に書くようにすることで、FeatureContextを弄る必要はなくなるはずで、将来プラグインのバージョンが上がってFeatureContextが書き変わっても問題はおきません。

CakePHPとの関係

まぁこのままだとただのBehatなので、プラグインは何をしてくれるの?というとCakeBehatと同じくapp/Config/database.phpの設定を元にテストデータを投入するためのインターフェースを用意しています。まぁそれだけなんですが(それを言うとスペックもアノテーション部分ぐらいしか…. )

先の日本語フィーチャでテストデータを登録するステップで、以下の2つのCakePHP連携APIが利用可能です。

  • truncateModel(モデル名) : 指定されたモデル名のテストデータを削除します
  • getModel(モデル名) : テストデータを登録するモデルのインスタンスを取得します(ClassRegistory::init(モデル名)と同じです)

テストデータは自動で削除されないので、このように必要なタイミングにてtruncateModelを呼び出すようにしてください。

ちょっと便利な機能

Behatは表面的には「前提 “トップページ” を表示している」のように表示するページを指定する場合はURLを書くようにガイドされています。しかし内部的には別名をURLに置き換える事も可能なので、BDDプラグインでは features/support/env.php にページ別名を書けるようにしています。この方がフィーチャファイルの可読性があがると覆います。

今後の展開

このプラグインを使ったBDDについてCakeFest2012の30分枠で話します。
その後、CakeBehatは完全にこちらへ移行となり(マイグレーションもそれほど難しくないと思う)ます。
Spec for PHPについては、私のdevelopブランチを利用しています。こちらは本家にはない機能(subjectもその1つ)を実装していたりします(そのうちPRするかも)。
Behat/Minkについても日本語問題をチェックしていたりしますので、統合的にメンテしていきたいと思っています。
また、これらで発生した問題についてもgithubのissueに日本語で構わないので指摘していただければと思います。

PHPのスペックフレームワーク

<!– more –>

PHPでのBDDについては、何度か取り上げてきましたがほとんどがストーリフレームワークであるBehatについてで、スペックフレームワークについてはあまりふれてきませんでした。せっかく今回はPHPカンファレンス関西のLTで2種類のBDDフレームワークについて話したので、スペックフレームワークについてまとめてみたいと思います。

最初にたどり着くのはPHPSpec

LTのスライドでも紹介したのはPHPといえばまず最初に思いつく PHPSpec です。大抵はまず「言語プレフィクス+Spec」で検索してみますよね。PHPはユニットテストがPHPUnitだからPHPSpecだよね、と誰もが連想できます。

で、PHPSpecの書き方としては、

class DescribeNewBowlingGame extends PHPSpecContext {  
    private $_bowling = null;  
    public function before() {  
        $this->_bowling = $this->spec(new Bowling);  
    }  
    public function itShouldScore0ForGutterGame() {  
        for ($i=1; $i<=20; $i++) {  
            // someone is really bad at bowling!  
            $this->_bowling->hit(0);  
        }  
        $this->_bowling->score->should->equal(0);  
    }  
}  

のように、まぁPHPのコードだとすれば読むのはそれほど困難ではないわけですが、やっぱりSpec(仕様)という視点で眺めると、ちょっと無駄な記述が目立ちますよね。それは言語の文法だからしょうがない、そうなんですが。

その他のスペックフレームワーク

で、試しにGitHubで他にないのかと探すと、意外とスペックフレームワークがある事に気がつきました。

名前所感

PHPSpec 最初に出てくる有名どころ

pecs JSpecに影響を受けている。しばらくメンテされていない…

spectrum まだα版でドキュメントもロシア語しかないが、設計の筋が良くいろいろできそう。今後に期待

speciphy yuya-takeyamaさん(@yuya_takeyama)がRspecに影響を受けて作成。subjectが使える。コアはPHPSpecを利用している

Spec for PHP Hamcrestライブラリとtokengetall関数を使って、自然に英語として読める文章として記述が可能。解析した結果をPHPUnitのテストケースとして生成して実行している

以下のコードは、Speciphy を例にPHPSpec以外でどのように書けるかをあらわしています。pecsもspectrumもほぼ同じような記述になります。

namespace SpeciphyDSL;
return
describe('Bowling',
    describe('->score',
        context('all gutter game',
            subject(function () {
                $bowling = new Bowling;
                for ($i = 1; $i <= 20; $i++) {
                    $bowling->hit(0);
                }
                return $bowling;
            }),
            it('should equal 0', function ($bowling) {
                $bowling->score->should->equal(0);
            })
        )
    )
);

だいぶ読みやすくなりました。ではRSpecと比較してみま….す?えっ、やっちゃうの、それは….

describe Bowling, "#score" do
  it "returns 0 for all gutter game" do
    bowling = Bowling.new
    20.times { bowling.hit(0) }
    bowling.score.should eq(0)
  end
end

こんな感じです。subjectやcontext使っている違いとかありますが、PHPの場合はどうしても無名関数を使うのに

function () {…}

を使わなくてはならないので、そこが惜しいのです。

変態PHPスペックフレームワーク Spec for PHP

そこで Spec for PHP ということなのですが、こいつはだいぶ変態です(ごめんなさい。良い意味です)。まず先程紹介したような funcition(){ … } の無名関数で書いたような記法も使えます。それはほぼ同じように書く事が可能です。で、何が変態かと言うと Hamcrestライブラリとtokengetall関数を使って構文解析することで、以下のようなSpecが書けちゃいます。

describe "Bowling"
  describe "#score"
    it "returns 0 for all gutter game"
      $bowling = new Bowling;
      for ($i = 1; $i <= 20; $i++) {
        $bowling->hit(0);
      }
      $bowling->score should equal 0
    end
  end
end

it ブロックの内容は、Hamcrestを使って$bowling->score should equal 0 のように書いていますが、基本的にはPHPのソースコードであるとわかるでしょう。ただしdescribeやitなどの構文からはfunctionが消えて見通しが良くなっています。

では早速試してみましょう

Spec for PHP は以下の依存関係を持っています。

  • PHP 5.3
  • PHPUnit 3.5
  • Hamcrest matchers library(ベータ版のときに作成されたらしい)
  • PHP Object_Freezer 1.0.0

この記事の執筆時点で最新版の依存関係を適用すると、PHPUnitとHamcrestを利用している箇所で一部エラーになってしまいます。そこで、これらを修正し本家にPull Requestを送付しています。
このため、本家に取り込まれるまでは、私のforkリポジトリから取得することを推奨します。

https://github.com/sizuhiko/Spec-PHP

上記問題に対応するための修正と、日本語関連でPHP関数名の正規表現に x7f-xff の範囲を追加した修正が、 develop ブランチに入っていますので、こちらでお試しください。

まず必要なpearパッケージをインストールします。すでにインストール済みならスキップして構いません。

pear channel-discover pear.phpunit.de
pear install phpunit/PHPUnit
pear install phpunit/Object_Freezer
pear install Console_CommandLine

Install Hamcrest matchers library
pear channel-discover hamcrest.googlecode.com/svn/pear
pear install hamcrest/Hamcrest

つづいて、githubからcloneしてdevelopにスイッチします。

git clone git@github.com:sizuhiko/Spec-PHP.git
git checkout origin/develop -b develop

Spec for PHPはPHPUnit経由の実行方法と、Cliランナーも持っています。

  • phpunit tests/AllTests.php
  • ./spec4php.php tests

さいごに

Spec for PHP はテストコードを書いていて楽しい気分になれるような気がします。まだまだ奥がありそうなので、ちょっと追いかけてみようと思っています。また本家にPRが取り込まれたときなどに、インストール方法など更新予定です。

また、PHPのスペックフレームワークについて「もくもく会」か「勉強会」をやろうと思っていますので、こちらは@sizuhikoのTwitterなどをチェックしておいていただければと思います。