フィールドテスト: conscript, giter8, sbt-dirty-money
Scala のツールを使った、日常のコーディングでのテクニックを紹介したい。 例えば、ツールとかライブラリを開発してるとして、バグ報告を受けるとする。まず原因の分析に入る前に僕が集中することは、ユーザが使っているのと同じデータで問題を再現することだ。問題が再現できれば、次に問題を単純化して失敗する spec や機能テストに落としこむことに移行する。バグが修正されれた後で、同じセットアップを使って実際のデータでもバグが直っているかを確認することができる。
conscript を使ったコマンドラインアプリ
最初に考えるシナリオはコマンドラインアプリだ。再現の部分はあまり面白く無い。普通のプロジェクトとは別に再現用のディレクトリを作って、そこにさらにサブディレクトリを作って、データを使ってアプリを実行するだけだ。 シェルスクリプトを用意すれば、色々パラメータを渡しながら実行するのには便利かもしれない。
僕が狙っているのは、ユーザと同じ環境下での、編集-デプロイ-テストのサイクルを短くすることだ。n8han の conscript 登場。conscript は、sbt の依存性の管理をバックエンドに使ったコマンドラインアプリをセットアップする簡単なユーティリティだ。 xsbti.AppMain
を拡張するクラスを含んだ jar を公開して、launchconfig
を github にプッシュするだけでいい。
ユーザが cs you/project
とアプリをインストールすると、conscript は、launchconfig
をダウンロードして、sbt-launch.jar
をlaunchconfig
と一緒に呼び出すシェルスクリプトを作る。つまり、この時点では、ユーザのマシンにはアプリの jar は存在していない。そこで、conscript は --version
という引数付きでシェルスクリプトを呼び出す。残りは、sbt のランチャーが適当にやってくれる。公開されている launchconfig
には、現行の安定バージョンを書くのが普通だけど、これをオーバーライドして任意のバージョンをダウンロードさせることもできる。これは、メインのエントリーポイントその他の設定が変わっていないことが前提だ。
準備ステップ:
-
プロジェクトのバージョンを
x.y.z-SNAPSHOT
に変更する。 -
アプリ
foo
をバージョンx.y.z-SNAPSHOT
でインストールする:$ cs you/foo/x.y.z-SNAPSHOT
編集-デプロイ-テスト:
- sbt から
> publish-local
- 別のタブでシェルから、
$ cs --clean-boot
- これも、シェルから
$ foo data.txt
便利なのは、このまま snapshot の jar を公開してしまえば、直ちにユーザが使えることだ。
giter8 を使った sbt プラグインのセットアップ
次にのシナリオは sbt プラグインだ。プラグインは便利だけど、使い捨てのプロジェクトのために設定するには面倒だ。n8han の giter8 登場。
Giter8 は github 上に公開されたテンプレートからアプリケーションのひな形を作成するコマンドラインツールだ。
you/foo.g8
をセットアップすれば、以下を実行すると:
$ g8 you/foo
src/main/g8
以下の全ファイルをダウンロードして、もし必要なら文字列置換を実行してくれる。
これを使って、プラグインをインストール済みの sbt プロジェクトを作っておくことができる。
編集-デプロイ-テスト:
- sbt から
> publish-local
- 別のタブでシェルから、
$ sbt run
これも、snapshot を公開してしまえば、修正は直ちに利用可能となる。
sbt-dirty-money を使った Ivy キャッシュの掃除
publish-local
にも問題はある。Ivy のキャッシュは、最後にどこから jar を取ってきたか覚えていて、それを使い続ける。これにより、「僕の環境では動く(他では動かない)」という状況を作り出してしまうことがある。~/.ivy2
を全部削除するというのは理想的ではない。sbt-dirty-money 登場。
このプラグインは、~/.ivy2
をもう少し選択的に削除するコマンドをいくつか追加する:
((dir / "cache") ** ("*" + organization + "*") ** ("*" + name + "*")).get
例えば、unfiltered/unfiltered からこれを実行すると unfiltered-xyz などにもマッチするので、明らかにこれは、完全ではない。
> show clean-cache-files
> clean-cache
上記は、~/.ivy2/cache
を組織名とプロジェクト名を使って削除する。
> show clean-local-files
> clean-local
上記は、~/.ivy2/local
を組織名とプロジェクト名を使って削除する。