今まで UglifyJS は単に圧縮としてしか使ってなくて、あまり細かく設定を見たことがなかったが、いざ触ってみたらいくつか発見があったのでそのメモを残しておく。
UglifyJS — JavaScript parser, compressor, minifier written in JS
まとめ
- 外部から define で値を埋め込むことができる
- UglifyJS の基本はコードの圧縮だが、その際に dead code の除去も行える
- source map の扱いにはややクセがある
define による外部からの設定の埋め込み
UglifyJS 自体は Node.js で動くので Node.js から環境変数を取得することはできるが、UglifyJS は Browserify ではないので、Browserify のように環境変数にアクセスしている部分をいい具合に置換してくれるわけではない。
そこで利用できるのが define.
- オプション –define でコード内の定数をセットできる
- literal に展開されるので文字列を埋め込むなどは難しい
- boolean だけに留めておくのが正解っぽい
- shell script の機能を呼び出して分岐させることはできる
uglifyjs --define PRODUCTION=`[ "$NODE_ENV" = "production" ] && echo "true" || echo "false"`
とやると JavaScript のコードの中では
if ( PRODUCTION ) {
...
} else {
...
}
のように参照して分岐させることができる。
compress
結構細かく制御できるし、default では割と積極的にコードが削除される。
例えばデフォルトの動作で dead_code を remove できるので、上のように if を書いておくと PRODUCTION が true の場合は then の中身だけが出力コードに残り、false の場合は else の中身だけが出力コードに残る。
他の assets や API の JSON を取得する処理はよくあると思うが、その URL は development, staging 環境と production で差し替えたくなるだろう。上のようなコードにしておくと UglifyJS の compress だけでそれが実現できる。(UglifyJS 後には if はなくなって差し替え後のコードだけが残る。)
source map
- source map オプションは output オプションの後に置かないと機能しない
- output オプションのパスを絶対に参照するみたい(中身は見てない)
- option の解釈が自身の生成向けオプションと読み込むソース向けのオプションと両方入っていて分かりにくい。これは UglifyJS がトランスパイルの最終工程に置かれることが多いゆえなのか、設計が古いのか、もうちょっと工夫してほしかった。
例えば uglifyjs 3.2.2 で確認したところ出力先のコードに source map を含めるには以下のようにする必要があり、
uglifyjs -o ./output/application.js \
--source-map url=inline,includeSources
さらにこの際、./output/application.js.map の生成は抑止できない。(ファイルの生成と inline への埋め込みがトグルするものと思っていたので指定に失敗しているのかと思ってしばらく悩んだ。)
ちなみに uglifyjs の前工程で source map を inline に生成している場合は以下のように content=inline を追加する必要がある。まぁその場合は最終工程の uglifyjs を省略すればいいだけじゃね?と思わなくもない。
uglifyjs -o ./output/application.js \
--source-map content=inline,url=inline,includeSources
cf. Emit inline source maps with UglifyJS v3 · Issue #2711 · mishoo/UglifyJS2
何がきっかけかよく覚えていないんだけど、この数日、急に Cucumber のことを思い出したので試してみた。
Cucumber は一部ではとても有名な受け入れテストの記述&実行フレームワークとでも呼んだらいいのかな。有名な記事はこの辺。
- Cucumberがアツい - moroの日記
- UK STUDIO - Cucumberの登場でRailsのテスティング環境が変わった
- Ruby Freaks Lounge:第21回 Railsアプリの受け入れテストをCucumberで書こう|gihyo.jp … 技術評論社
まだあまり詳しく本家ドキュメントを読んでないんだけど、あちこちの記事から分かることは、これは
外部仕様あるいは要件定義を共有しやすくするフレームワーク
ということでしょうか。あたかも自然言語で書いたプレーンテキストがテストを動かすスクリプトとして機能しているように見えるので、今の動作で仕様を満たしています、あるいはここまでできています、ということを開発者間、開発者とマネージャ、プロダクトオーナーと共有しやすくなることが嬉しいみたい。
なんのこっちゃって感じですか?
機能的な部分をごく大雑把に言い直すとテスト用の DSL を提供して、そこからあれこれテストツールを呼ぶよ、って感じです。こっちの方が具体的な動作はイメージしやすいかな。
あとは
examples at master from aslakhellesoy's cucumber - GitHub
ここら辺のコードを眺めて動かしてみるとつかめると思う。
もちろん有名なのは Rails のテストなんだけど、例えば Ruby の Test::Unit と連携することもできるし、Webrat というツールを使うことで PHP アプリをテストすることも可能。
PHP アプリのサンプルがなかったので探したみたら
Cucumber+WebratでPHPアプリのテストをする | CAPH TECH
が見つかった。ただしどうもちょっと古いバージョンをもとにしているらしく、0.6.3 では動かなかった。Ruby 1.8.7 + Cucumber 0.6.3 で動かすにはこんな感じで修正が必要。
diff --git a/cucumber.yml b/cucumber.yml
index c39f416..c1869b5 100644
--- a/cucumber.yml
+++ b/cucumber.yml
@@ -1 +1 @@
-default: --language ja features
+default: features
diff --git a/features/show.feature b/features/show.feature
index e3afa77..3887cb7 100644
--- a/features/show.feature
+++ b/features/show.feature
@@ -1,3 +1,4 @@
+# language: ja
機能: トップページの表示とサブミット
シナリオ: トップページの表示
diff --git a/features/step_definitions/result_steps.rb b/features/step_definitions/result_steps.rb
index b22e762..85c2824 100644
--- a/features/step_definitions/result_steps.rb
+++ b/features/step_definitions/result_steps.rb
@@ -1,11 +1,11 @@
# -*- encoding: UTF-8 -*-
ならば /^"(.*)"と表示される$/ do |text|
- response_body.to_s.force_encoding("UTF-8").should =~ /#{text}/m
+ response_body.to_s.should =~ /#{text}/m
end
ならば /^"(.*)"と表示されない$/ do |text|
- response_body.to_s.force_encoding("UTF-8").should_not =~ /#{text}/m
+ response_body.to_s.should_not =~ /#{text}/m
end
ならば /^(\w+)メッセージが表示さる$/ do |message_type|
diff --git a/features/support/env.rb b/features/support/env.rb
index 54a9528..87f3521 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -1,5 +1,6 @@
# RSpec
require 'spec/expectations'
+require 'cucumber/formatter/unicode'
# Webrat
require 'webrat'
diff --git a/index.php b/index.php
index 5623672..bac22ea 100644
--- a/index.php
+++ b/index.php
@@ -9,7 +9,7 @@
<?php if(!isset($_GET['text']) or empty($_GET['text'])) print '<p>テキストを入力してください。</p>'; ?>
- <form action="/php_with_cucumber/index.php" method="get">
+ <form method="get">
<p><textarea name="text" rows="10" cols="100"></textarea></p>
<p><input type="submit" value="Submit" /></p>
</form>
簡単に言うと
cucumber-0.5.0へ上げるときの注意点 - ヽ( ・∀・)ノくまくまー(2009-12-21)
を読めって話になります。読め。ただし、
require 'cucumber/formatter/unicode'
はちょっとした罠かも。example を読んでれば気づくけど。
あと以下の部分でテストするアプリの URL を決め打ちしてるので、対応が必要。
features/step_definitions/webrat_steps.rb
# -*- encoding: UTF-8 -*-
前提 /^(.*)ページを表示している$/ do |path|
@response = visit "http://localhost/php_with_cucumber#{path}"
end
もし /^(.*)ページを表示する$/ do |path|
@response = visit "http://localhost/php_with_cucumber#{path}"
end
もし /^"(.*)"ボタンをクリックする$/ do |button|
こういうのちょっとダサイよねぇ。開発環境、検証環境、本番環境の違いをもうちょっとスマートに書き分けたり、開発環境の URI が増えていっても対応が楽になるような工夫がないものかしら。1
感想
Webrat って Mechanize と何が違うの? と思ったら内部に Mechanize 用の adapter があって、実行時のレポートで Mechanize の警告が出たので、結局実際に外部のアプリにアクセスする部分は Mechanize を利用しているらしい。ここら辺、依存が深くなってきてちょっとややこしい。
また、Rails には plugin があるので Cucumber は使い始めやすいと思うんだけど、素の状態から使うのはちょっと面倒かなって感じがした。example レベルに留まっている step の記述がもっと充実してくれば違うんだろうけど、今のままだと
- プロダクトコード
- テストストーリー
- ストーリーを記述するための step
を書かなきゃいけないし、step はどうしても Ruby で書かざるを得ないのでプロダクトコードを別な言語で書いている場合はかなり面倒なことになってしまう。
ただし、その面倒をあえてやるべき場面もあって、それは内部の作り替えのとき。Cucumber で外側のテストがしっかり動かせていれば中の設計、もっと言えば中の環境はどうでもいいと言える。レガシーコードに悩んでいるアプリも、外を固めて差し替えてしまうことができるようになる。個人的には Mechanize はだいぶ慣れてきてるので、うまく使えれば動作の変化を最小限に抑えつつ古いコードを捨てるために使えるんじゃないかと考えている。
※ 学習曲線の初期段階においてにはちと荷が重い取り組みなので、試しに採用できそうな適切なサイズのアプリの見極めが大事になってきそう。自分の手もそれに集中させるのは難しいだろうし、古いアプリの仕様を後から書かなきゃいけないのも大変。現場は常に理想の正反対を行っているのだなぁ。でもそれがあるから新しいアイディアを思いつき、新しいツールが生まれてくるんだろうけど。
そもそも本番環境を Cucumber でテストするっていう考え方がおかしいかもしれなので、必要ないかも。 ↩
以下、確認は
- OOo 1.1.3 on Win
- NeoOffice/J 1.1 Beta Patch 9
- Word 2000 on Win
で行っている。
背景
- Office はコストパフォーマンスが悪いのでできるだけ数は用意したくない
- しかし Office で読める形式にすることを求められることがある
- Office のドローツールは概して使いにくく1、最終的に Office で読める形にするときでもドローは別なものを使いたい
- したがってベクトルグラフィックスを文書の中に「配置」する必要があるが、これをまともに実現できる組み合わせをはっきりさせる必要がある
作成
- Word では eps を [ 挿入 ] で貼付けてベクトルグラフィックスを活かすことができる
- 2000 より 2003 の方が扱いはいいみたい
- すべてのバージョンの eps に対応できるわけではないので、確認が必要
- OOo では WMF を使ってベクトルグラフィックスを含む文書を作ることができる
- NeoOffice/J では WMF を使う方法は不可
- OOo も NeoOffice/J も eps のベクトルグラフィックスを活かすことはできない
- したがって NeoOffice/J ではベクトルグラフィックスを活かした文書作成は不可能
- Pages は Preview からのコピペでベクトルグラフィックス入りの文書を作成できる
- Preview で開ける eps は以下の通り2
バージョン | 可否 |
5.5 | × |
6 | ○ |
7 | ○ |
8 | ○ |
まとめ
- Windows 環境ではフリーの OOo で WMF の貼付けを行ってベクトルグラフィックス入り文書の作成が可能
- OS X ではフリーの NeoOffice/J だけではダメなので、eps を始め様々なデータ形式へ対応できる Pages(iWork)を購入して文書作成するのが安上がり
- どうしても NeoOffice/J でやりたい場合は、大きめにラスタライズして NeoOffice/J 上で縮小する。ただし文書のデータサイズはベクトルグラフィックスを利用する場合より大きくなる。
- AppleWorks やクラリスワークス、OOo で完結させることができるならそれ使えばいいんだけど。
OS X で MS Office を使わずに頑張る
- Pages の作成する Word DOC では eps はラスタライズされている
- 開いてみると OOo でも NeoOffice/J でも画像の位置がずれている
ということで文書の互換性という意味では Word 形式のサポートには期待しすぎてはいけないと考えるのが妥当。読めることは読めるが手直しが要る。楽したいなら素直に Office3を買えと。
結論
- Windows 環境では WMF と OOo で結構使いものになる
- OS X 環境では Pages があるとあれこれデータを貼付けてきれいな PDF の生成は可能だけど、その貼付け終わったデータを Windows で再利用したいというのは難しい
- Windows 環境でも OS X 環境でも eps などの素材は文書とは別な形できちんと保存しておくのが望ましい
うわー
Pages の作るファイルは OS X のアプリ群と同じく、実際にはパッケージなのね。他のプラットフォームで開くとびっくりするので、共有スペースに保存する場合はアーカイブにしてからの方がいいかな。
保護しようと思った。理由は編集できちゃうとバックアップとして機能しなくなるから。で、-w にしちゃえばいいやーと思ったら permission denied で PukiWiki がまともに動かんくなった。
あほかおれは。
PukiWiki の認証部分に手を入れて xrea.com 上で動いている場合に限り編集を許可するようにしないといけないんだった。帰ってからゆっくりやろう。(仕事中に何してるんだ。)
はい。できました。
いつまでも放置もどうかと思い、とりあえず入れようと思った
sudo portinstall -m WITH_CHASEN=yes namazu2
が、
===> Installing for expat-1.95.7
===> Generating temporary packing list
===> Checking if textproc/expat2 already installed
===> An older version of textproc/expat2 is already installed (expat-1.95.6_1)
You may wish to ``make deinstall'' and install this port again
by ``make reinstall'' to upgrade it properly.
If you really wish to overwrite the old port of textproc/expat2
without deleting it first, set the variable "FORCE_PKG_REGISTER"
in your environment or the "make install" command line.
で止まった。なんかこの辺も Emacs を package で入れた名残りのような気がする。えーい面倒くせえ。