布都ちゃんが可愛すぎて生きるのが辛い。mix3です。
テスト書くのって難しい
なんの意味も無い以下のような糞コードがあったとして、各subについてテストを書いたりなんかしてみるとこんな感じだろうか?
なんでこんな糞コード書いたかというと
- type_a, type_b
- まあ良い
- type_to_execute
- type増えたらやだなぁと思うけどまあ良い
- calc_type
- 計算複雑になったらやだなぁと思うけどまあ良い
- execute
- type_a,type_b,type_to_execute,calc_typeが総じて複雑になった時、全部と通るテスト書くの考えたくないんだけど…
普通にアプリ書いてると、色々複雑になった上でexecuteみたいにいくつも関数経由して結果を返すやんちゃな関数が出てきてしまうのですが、そういうののテストは正直書いていて死にたくなります。そして後で機能拡張しようとしてやっぱり死んだりする。
「そもそも設計が悪いよ」「それ◯◯で出来るよ」「糞コードに何を求めてるの」etc… ということなんでしょうか。テスト大事なのは分かるのですが、正しくて網羅的なテストというのはきちんとスキルを身につけてないと出来ないよなぁと思う事が多いです。「書かないよりはずっと良い」と心の中で言い訳しながら書いてますが。
ただ、以下のような事もあるのでやっぱりただ書くだけでもダメなんだなと思いつつ、もやもやする今日この頃です。
リファクタリングに使えないテストのことをレガシーカバーと呼ぶ。結局リファクタリングできないんだからレガシーコードのまま。
— いろふ(成分無調整) (@irof) June 18, 2013
うわっ…私のチーム、レベル低すぎ…? mix3です。リードエンジニアとしてどうにかしろって話ですが、コミュ 障の自分には荷が重いです…
PhantomJS: 最小限なheadlessのWebKitベースのJavaScriptツール
だそうです。正直良くわかりませんが、nodeのようにサーバーサイドで書けるイメージ。
$ cat hello.js
console.log('Hello, world!');
phantom.exit();
$ phantomjs hello.js
Hello, world!
とか
$ cat google_capture.js
var page = require('webpage').create();
page.open('http://www.google.com', function (status) {
page.render('google_capture.png');
phantom.exit();
});
とか
$ cat hello_server.js
var system = require('system');
if (system.args.length !== 2) {
console.log('Usage: hello_server.js <portnumber>');
phantom.exit(1);
} else {
port = system.args[1];
server = require('webserver').create();
service = server.listen(port, function (request, response) {
response.statusCode = 200;
response.write('<html><body>Hello, World!</body></html>');
response.close();
});
if (!service) {
console.log('Error: Could not create web server listening on port ' + port);
phantom.exit();
}
}
$ phantomjs hello_server.js
$ curl http://localhost:2525
<html><body>Hello, World!</body></html>
などなど。単純なCLIプログラムや、Webページにアクセスしてキャプチャ取ったり、サーバプログラムも書けたりします。
ローカルファイルも扱えるので、例えばあるディレクトリ以下の画像を並べて表示するサーバを立てつつ、それを
page.open('http://localhost:[port]', function () {
page.render(...);
});
とかするとあら不思議。コマンド一発で複数画像を1枚画像に出来たりします。
なんでこんなもん触ってるかというと
ソーシャルゲームに携わっていて思う事なのですが、イベント中だと特にそうですが時間で文言が変わるということは良くあることです。そしてこういうものは当然リリース前にスケジュールはきっちり決まっていて(もちろん差し込みで仕込み直すこともありますが)がっつりテストすることになります。が、開発段階でも当然自分で目視チェックすることになるのですがこれが非常に面倒くさい。なぜ面倒くさいかというとモジュールの単体テストとは違いローカルプロキシ越しにブラウザで確認したり実機で確認したりすることになり、自動テストになかなか上手く落とし込めないからです。(見た目の部分は特に変更が出易いのでそういう意味でもテストに落としづらいというのはあると思います)他のプロジェクトだと一部定型的な部分はモデルに落とし込んでテスト出来るようにしていたりするようですが、当然限界もあり。
ということで、今のところ画像、文言など見た目の部分をテストに落とし込むのは無理だろうなぁと思っておりますが、そうは言ってもチェックが面倒なことは面倒なのでチェックすること自体はいくらか楽にはしたい。特に時間で文言が切り替わるのを見比べられる状態にしたい。
ということでphantomjsでしこしこ以下のようなスクリプト書いてました
- 指定ページを時間別にキャプチャしてpngで吐き出すスクリプト
- フォルダ以下の*.png画像を横に並べて表示するサーバを立ててそれをキャプチャするスクリプト
参考: PhantomJS でログインが必要なページでも自由自在にスクレイピング - 凹みTips
ほぼほぼキャプチャの部分は参考をそのまま使わせてもらっているのですが、参考のままだと画像などがキャプチャされないことがあったので、setTimeoutを使ってキャプチャのタイミングを遅らせるなどの簡単な工夫をしています。
後、サーバがバイナリを出力するときは、ローカルからファイルを読み込む時に 'b' を指定するのとresponse.writeするまえにresponse.setEncoding('binary')しないといけないようなので注意が必要です。
var image = fs.read(file_path, 'b');
response.headers = {
'Accept-Ranges': 'bytes',
'Content-Type': 'image/png',
'Content-Length': image.length
};
response.setEncoding('binary');
response.write(image);
こうすることで横並び画像にして文言チェック出来るようになり捗りそうな気配がしています。(まだ作ったばかりで実際に活用するのはこれから)
ちなみに一枚画像にしてしまうのは社内gyazoにあげてディレクターなど他の方にも見てもらえるようにしたかったからですが、今にして思えば別に一枚画像にする必要はなく、画像一括アップロード出来るフォームと横並びにして表示出来る簡単なサーバアプリを書くだけで良いことに気づいたので、ここは今後やりやすい方にシフトする感じで行きたい。
ということでphantomjs便利なんじゃないかなというお話でした。
これ書くタイミング間違えてる気がするけどまあいいや
なんとなく作ってみるなど。別に他フレームワークと差別化して使うようなものでもなく習作的な感じ。
*::LiteとかDancerとか使えばワンソースでお手軽にWebアプリ書けるわけですが、実際に簡単なアプリ書くとなると、Liteなんだけどなんとなく仰々しい気がしてきたり。(Liteと言っても結局各フレームワークが持つ色々な機能は提供されているのでそう感じるのかな?)
でもだからといって
my $app = sub {
my $env = shift;
[200, ['Content-Type' => 'text/plain'] ['Hello World'] ];
};
$app;
とかをモリモリ書いちゃうのもどう考えたって違う。
ということで、Plack::*,Router::Simple(Router::Simple::Sinatraish),Text::Xslate,Data::Section::Simpleでそれっぽく書けるようなものを作ってみた。あまりにも決め打ちすぎるので、設定を渡せるようにしたりして融通効くようにしたいかな。あんまり迷惑にならなそうなところで使ってみてます。
「劣化MojaMoja」とか「劣化Hitagi」とか「劣化Shirahata」とか思いつつ、劣化ということすらおこがましい状態。そりゃ大半コピーアンドペーストだもの仕方ないね。
強いて特徴を上げるならフォワードっぽいこと出来るようにしてみた($ENV{PATH_INFO}をlocalで書き換える力技なので問題あるとは思う)けどSinatra的ルーティングでフォワードは用途を勘違いしてる感が否めないので正直いらないと思います。マル。
ちなみにChacoはチャコと読みます。以前実家にいた、今は亡き黒のラブラドールレトリーバーの名前です。
use Chaco;
# ...
run;
で、元気に走り回るチャコの姿を思い浮かべながら書いてました。以前書いた絵の日付みてもう4年近くも経ってるんですね…
Perlのネガティブキャンペーンが流行ってる今日この頃ですが私は元気です(震え声)
p5-JQueryPresentationHelperなんてなかったんや
Plack::App::Directoryで画像とかは展開してほしい
Plack::App::Directoryでカレントディレクトリ以下を見えるようにするワンライナーをbashrcとかでエイリアスにしておくとか良くあると思います。凄く便利なのでそれはそれとして良いのですが、画像とかは出来れば展開してそのまま見えてほしいかなと思う事もあります。
なので、どうすれば良いかなとPlack::App::Directoryの中見てたのですが、もりもりっとtrタグを羅列してるだけっぽかったので、HTML出力を正規表現でちょちょっと弄ればそれっぽくなりそうだと思ったのでやってみました。
ファイルを出力するときはPlack::Util::IOWithPathのオブジェクトを返してるようなので、そうでないときだけ正規表現でちょちょっと弄る感じですると良い感じに画像表示してくれました。
swfも見えてほしいなぁという声が聞こえてきたのでswfobject.jsで見えるようにしてみました。
タイルで見えるともっと良いね!という声が聞こえてきましたが、Plack::App::Directoryを使う限り無理なので、それは新規で別モジュール作った方が良いなと思いました。
ちなみにswfobject.jsは2.2でもまだ微妙にセキュリティリスクがあるらしい ほむらちゃほむほむ - swfobject.js がアレな話 ので外から見えるところで使うのは止めた方が良いかなと思います。
やりたかったこと。
- use Hoge でメソッドが生えるモジュールの習作が作りたかった
- jquery-presentation:demoをmarkdownで書けるようにしたかった
結果、良くわからないものが中途半端に出来てしまって、でも放置してもあれなのでとりあえずgithubにアップ。
git clone を前提としたもっとゆるい感じで作った方が良い感じにおさまった気がしてます。
jquery-presentationに依存したDSLモジュールとかcpanにあげるわけもないのだし。