ノーフレームワークのレガシーPHPがCIに乗るまで

ついに仕事で触っている PHP のコードがほんの一部のテストとは言え CI に乗った

正直これは感動ものだ。

今回はここに至るまでの長大な物語をダイジェストでお届けしようと思う。

有史以前

  • PHP 3 で作られた 1 URI : 1 スクリプト + 共通関数 時代
    • 当然のように PHP と HTML と SQL 混在
  • まともなテスト環境がなかったので似た環境をどうにか作る
  • パスとか絶対で埋め込みまくりなのでとりあえず共通のパス情報の変数に差し替えまくり
  • テスト環境用のコードと本番環境用のコードが違う

オール目視

つらかった。

みなさんの予想通りバージョン管理なんてものは存在しなかった。

素朴なPHPを徐々にclassに

  • class になれば phpdoc を書きやすくなる
  • いきなり実行しないようにすればテストしやすくなる
    • これは後から気づいたんだけど、結局フロントはロクに自動テストできてない

一時期 phpdoc に夢中になっていた。今も大事に思ってはいるが、完全に独立したライブラリのドキュメント以外には助けられた感じはあまりしない。

とりあえずテンプレートを導入してHTMLを分離

当時はテンプレートにはロジックは入ってはならないと頑なに信じていたんだけど、おかげでテンプレートを制御するコードが妙に複雑になることに徐々に気づき、Rails の View を erb で書いて以降は

結局 PHP の <?php ?> 方式は適切なスコープの分離ができないことが問題なだけで、そんなに悪くなかったんだなぁ

と思っている。

ただ PHP の <?php ?> 方式はあまりに問答無用でかなりダメだと思うけど。

とりあえずCLIで叩き回る&目視

PHP 5 への移行時に苦し紛れで使ってた方法。今の capybara のようなツールを知らなかったのでひたすら PHP の cli バイナリで実行しまくった。

  • とりあえずすべてのフロントの PHP を find で洗い出して、cd して1叩きまくる2
  • これでも致命的なエラーはだいたい洗い出せるので、これを毎日 cron で回して通知させて片っ端から直した

しかしテンプレートオブジェクトが clone されたかどうかがキモになる部分がいくつもあり3、最後は目力頼みに。

今ならなんとかこれもテストできるだろうなぁ。

本番サーバの監視ツールを自作

頑張って自動で叩いたり目視したりしてたけど、やっぱ網羅はできなくて、どうしても本番サーバで問題が発覚したりした。仕方ないのでログを監視することにした。と言ってもそんなにたいしたものではなく、Webサーバの error log を監視して PHP の E_ERROR とか E_WARNING を拾って通知するだけ。

Rswatch なんてものを書いてみました

要するに拡張性の乏しい Swatch を Ruby で再発明したということです。今ならもっと賢いツールがたくさんありそう。当時は標準のパッケージで入らないものはできるだけ避けたかったのと、環境が古いので自作した。PHP 5 への移行期に 4 でも 5 でも動くようにしながら、本番環境の 4 で問題が起きたかどうかを早く知るために書いたものであり、想定している Ruby のバージョンは 1.6.8 である。すごい。

書けるところからユニットテストを

実は少し PHPUnit でテストを書いていた時期がある。しかし PHP 5 への移行を考慮して割とすぐに SimpleTest にした。当時は PHPUnit が PHP 4 用で PHPUnit 2 が PHP 5 用と分離していたのに対して SimpleTest は両対応で、テストコードを資産として残しやすいと判断したため。

以来、結局 SimpleTest を使い続けている。

今もメンテは続いており、ややマイナーではあるもののなかなか良いツールだと思う。

現在のコードは徐々になんちゃって MVC になっており4、少なくとも M の部分とヘルパーやユーティリティ的な部分は独立してテストできるので、だいぶマシになっている。

正直どんな機能にするかよりもどうやったらテストできるか、どうやったらオブジェクトの独立性を確保できるかをいちばん考えているかもしんない。

これは以前も書いたけど要するにリファクタリング及びコードの変更をやりやすくするため。どうせ自分は失敗するから。

TestCaseからTestSuiteへ

目の前の課題にいっぱいいっぱいだったのと、当時 SimpleTest には auto runner もなく、余計なコードはできるだけ書きたくないのですべての TestCase を手で叩く仕様にしていた。本当に余裕なかったんだなぁ。

これがのちのち効いてくる。TestSuite にしようにも require した瞬間にテストが走るのでまとめることができない。しばらくして production のコードと同じく

if ( realpath( $_SERVER['SCRIPT_FILENAME'] ) == __FILE__ ) {

}

でテストの実行を囲んで、今は TestSuite を叩くとすべてのテストが自動で走るし、個別にも実行できるようになっている。

auto runner をちゃんと使うとまた違うのかも。まだうまく試せてない。PHP のバージョンを上げることができたら A continuous test runner for CLI v3 - Stagehand_TestRunner - Piece Framework を導入して楽したい。

end-to-endテストはRubyでやろうとしている

PHP にも Behat という Cucumber inspired なツールがあるんだけど、これは PHP 5.3 以降を要求するという、なかなかにハードなシロモノである。

まぁ CI サーバを 5.3 で組んだので CI サーバ上では使えるんだけど、CI でしか動かないのは面倒だし、すでに RSpec は使えるので RSpec + capybara-mechanize でいいじゃんと思っている。

ちなみに Cucumber 系はちょっと準備が面倒なのと、いちばんの理由はシナリオファイルはどんな言語でもないのでエディタのサポートが弱いという点で導入には躊躇している。テストの書き方をミスった場合にその発見に時間が掛かりそうなので。

まだこれでイケそうという手応えをつかんでいるだけで、具体的にはそんなに作業は進んでいない。

end-to-end のテストが整備できたら、今の中身はバッサリ捨てたいなと思っている。

※ ちなみに、完全に自動化するのを諦めて実装時の反復だけとにかく速くするために Selenium は導入していた。最近はあんまり使ってないけど5

結論

ゼロから作れるならとにかくデキのいいフレームワーク使え。

特にテスト支援は安心を、DBのmigrationは勇気を与えてくれるので重視した方がいい。

CI も最初から導入しろ。テストなしに繊細なコードを書くことに比べれば Jenkins の導入は信じられないくらい簡単だ。簡単で効果の大きいことから始めた方がいい。

自分がスーパーハッカーでもっとずっとプログラミングできる立場なら、もっとずっと早くなんとかなったんだろうなぁ。

  1. なぜならブラウザからアクセスしたときはスクリプトの場所が cwd になるのが PHP の仕様だから、これをアテにしまくっているのだ 

  2. 実際にはややこしい例外がいくつもあったので YAML で除外対象を定義できる Ruby スクリプトを用意してそれで回した。 

  3. PHP は 4 から 5 になる段階で、それまで代入時にデフォルトでコピーされていたオブジェクトが clone で明示しないとコピーされないように変更された。この影響が思いのほか大きかった。しかもこの変更はオブジェクトに対してだけで、built-in の array などはそのままなのでかえって混乱のもとになっていると個人的には感じている。 

  4. 間にとりあえずフロントコントローラ方式のオレフレームワークを組んでみたりした。これは当時増えていたフレームワークがほぼ PHP 4.3 以降を要求するのに対し、利用していた環境が 4.2 だったから。この環境の制約とそれを乗り越えるためのオレライブラリ、オレフレームワークの実装はとても勉強になった。どれくらい理解していたかと問われると甚だあやしいが、Rails や ZendFramework を参考にしていた。 

  5. 不安になるのは必要な情報が正しく伝わるかどうかなのに JavaScript だけでは Model の状態が分からず、どーも内部の変更の影響を受けやすい。今の自分の力では fragile test になりやすい。わざわざ rc から PHP で〜みたいなことを考えるのも割に合わない感じなので諦めちゃってる。どうしても必要なときだけ Selenium IDE から HTML 吐き出して使い回したりする。 

Google Form は基本的にガラケー非対応か

sensitive な情報でなければ十分使えると思う Google Form だけど、実際使ってみていちばん困ったのは

日本のケータイには基本的に対応していない

ということだった。今さら何言ってんだと思うかもしれないけど、案外書かれてないんだよね、これ。

試したところ

  • 少なくとも2009年春モデルまでの NetFront は利用不可
    • i-mode 2.0 は知らない
  • Openwave は
    • 7 は OK
    • 6 は NG
  • 同じく Google のサービスである Wireless Transcoder 経由だとイケるという情報も見つかったが、手元で試したところ、かえってひどくなった

という状態。

まぁ、だからどうしたという話でもないんだけど、メモということで。

実は i-mode 2.0 では動くようになっていて、日本のアクティブなモバイルユーザーの大半はカバーできてたりするかもしれないけど、その辺の調査の数字が出そろう頃にはまた状況が変わってたりするんだよねー。

メントレGゴールデン

レストランのライティングは深夜の方がよかった。あの変なピカピカフィルタはアレだったけど、ライティングは絶対深夜の方がよかったよー。ライトが増えて画がフラットになってるじゃないか。こういうのもったいないと思うんだなぁ。少なめのライトでドラマティックに… NHK とかね、ああいうのがいいんだね。やっぱね。レンブラントライティングが大好きだから。

Firefox 1.0.2

OS X 版を使った感想。

  • アドレスバーの文字が小さくなった
    • Sage のリストとかポップアップした JavaScript のダイアログとか軒並み小さい
    • なんか前に userChrome とかでいじってたような気がするのでデフォルトに戻っただけなのかも
    • てか戻るのってどうだ?
  • Internet Keyword(アドレスバーから直接検索できる機能)を使って日本語の一つの単語で検索すると punycode で検索してしまって使いものにならない
    • 複数の単語で検索している場合は問題ないし、「keyword:」をつければ問題ない

punycode の問題は about:config から

network.IDN_show_punycode false

にして解決。本当は punycode 表示した方がいいんだろうけど、以前出来ていたものができなくなるのも困るのよね。(サーチバーはアドレスバーが狭くなるからきらいなのれす。)

しかし、OS X のブラウザは印刷時のヘッダ、フッタの出力を指定できないものばかりなのはなんとかならないのだろうか。せっかく CSS できれいに整えてもヘッダ、フッタの出力を抑制できないとかっこ悪い。。。ひょっとしてヘッダ、フッタも CSS で制御できるのか?

まだまだあぶない刑事

すげー出遅れた。今日になって知ったよう。

しかしまたやってくれるんですか。たぶんもう売れないと思うけど、おれは見るよ。見ますとも。テレビも映画も全部見てるんだから、見る義務があるさ。あーでも世間は80年代に回帰しつつあるから、ひょっとするといいタイミングなのかな? マイアミバイスもまたやるし。

ゆとり教育論はアンジャッシュの思い込み会話芸だ

たった今思いついた。こういうのをちゃんと盛り上がってるときに思いつかないのが情けない。世間的にはたぶんゆとり教育論はもう終わってるだろうなぁ1

「教育ネタに飛び火したオレオープンソース論」ていう形容は、実は早いうちに思いついてたんだけど、これだとピンとくる人とこない人の差が激しそうで、見送っていた。

くやしいけどここに書いて自己満足しておこう。

  1. ゆとりに限らず教育ネタは自分の狭い世界だけで話が終わっちゃうもんだけど。 

ケータイきらいなだけちゃうかと

教師のケータイ」 (朝日わくわくネット)

論理がない。ハナから携帯がきらいなだけである。ただ、最後の、本当に最後の部分にだけはうなずけた。

欠席した児童の様子をたずねるのにケータイから家に連絡した同僚が「相手の電話機がナンバーディスプレイだったらしくその後、何かあるたびに学校を通さず、直接ケータイに連絡があるのだけれど‥」とこぼした。便利だからと安易に私的なケータイを私用しがちな昨今、教師とケータイについて今一度考えてはどうだろうか。

問題はここだけだろう。

ケータイを持つことを否定するのはすでにナンセンスの域に入っていると思う。小学生が持つのとはワケが違うのだ。だからケータイの話は利用節度と備品管理と、これらを集約した学校経営体制の話に集約すべきだと思う。

コンプレックスさえも言わばモチベーション

バブル入社組、14年目の宿命」 (asahi.com)

心が折れる前に、自分の武器を点検しよう。

About

例によって個人のなんちゃらです