AsakusaFWのデータモデルドライバーを拡張して独自の処理を行えるが、ドライバーのMainクラスを直接実行する方法しか知らなかった。
が、通常のモデルクラス生成時に独自ドライバーを組み込む(実行させる)方法が分かったので、メモ。
正統な(?)方法としては、やはりMavenのpom.xmlに依存関係を追記する。
独自ドライバーはMavenのローカルリポジトリーに登録しておけばよい。
ただ、Mavenに慣れていない身としてはちょっと大仰に感じるのでw、慣れたAntのbuild.xmlを修正する方法もある。
Mavenから「mvn generate-resources」を実行すると、巡り巡ってasakusa-build.xmlのモデル生成タスクが呼ばれる。
これがドライバーのMainクラスを実行しているので、ここの引数にプラグインとして自分のドライバーのパスを追加しておくだけ。
ほんと、AsakusaFWの拡張性は素晴らしい。
第4回Asakusaソースコードリーディングに参加しましたので、そのメモです。
資料: TestDriver/CI
Togetter: Asakusaソースコードリーディング第4回(#AsakusaReading)
今回のテーマはテストドライバーとCI(継続的インテグレーション)。
発表者は@apirakunさん。テストドライバーの設計/実装の担当者で、AsakusaFWのCIの仕組みも作ったそうです。
まずはテストドライバーの概要・方針から。
AsakusaFWでは、各DSLのテスト方法を提供している。
Operator…通常のJavaとしてテスト
FlowPart…DSLをコンパイルしたMapReduceに対してテスト
JobFlow…外部インターフェース(ThunderGate)と連携したテスト
Batch……ワークフローエンジン連携機能と連携したテスト(ワークフローエンジンとは、例えばMonkeyMagic)
#“外部インターフェースとの連携”はFileImporterやExporterのこと
##FlowPartとJobFlowの違いがあまり分かっていなかったが、入出力が異なるんだ!これは明快な差だなぁ
#“ワークフロー連携機能”というと、何か連携用の機能を持ってる?
##ほとんどJobFlowのテストしか動かしてないからイメージが湧かないや^^;
テストデータの作成をExcelで実装していることには賛否両論あったそう。でもDBUnit使うと大変だとか。
AsakusaFWの最終的な入出力対象はDBとSequenceFileだが、テスト時には違いを隠蔽している。
テスタビリティーの追求として、
1.テストが自動化できること→CIに乗せる(迅速なフィードバックを行う)・過剰な機能は削る
2.各DSLが同じ方法でテストできること
3.テスト実装方法を迷わないこと→分かりやすいようにする(シンプルにする。ただし自由度は下がる)
4.通常のJava開発と同様にテストできること→Eclipse+JUnit
5.ローカルでテストできること→最初はCI環境・擬似分散モードでテストするつもりだったが、擬似分散環境はフィードバックが遅いので、スタンドアローンベースに方針転換した
↓↓↓↓↓↓↓↓
で、これらの方針はAsakusa Test Driver 0.1でほぼ達成できている。
しかし0.1では汎用性が無い(外部連携はThunderGateのみ、テストデータの記述はExcelのみ)ので、0.2でリアーキテクト(アーキテクトを変更)した。
0.2のNew APIは「XXXTester」というクラス名になっている。
・ThunderGate以外にも対応
・JSON・Excelに対応
・ExcelファイルはCalc(OpenOffice.orgの表計算ソフト)でも使えるようになった
・(Ashigelコンパイラーと同じく)SPIで拡張できるようにした
ExcelファイルがCalcでも扱えるようになったというのは地味に重要なようで、Windows環境以外だとExcelファイルを扱おうと思ったらOpenOfficeで使えると便利だということらしい。
ただ、今でもSI企業では基本がWindowsなので、通常のJava(Webアプリとか)の開発でもWindowsで単体テストし、結合テスト以降をUNIX機で行うことが多い。(うちの会社も典型的にそれですよorz)
なので、それを踏襲した方が受け入れやすくなるのは確かだろう。
ただ、Hadoopに限らず、今後新たな分散環境アーキテクチャーも出てくるだろうから、それも考慮して開発環境(テスト方法)を考えた方がよいとのこと。
TestDriver 0.2は、
Compiler(バッチのコンパイル)→Preparator(プリパレイター:データのインポート)→Executor(実行)→Inspector(検証)
順で機能が動作する。
↓↓↓↓↓↓↓↓
今後の機能強化として、テストを短時間で終了させるようにしたい。方法は2通り考えられる。
・Distributed Testing…テストを複数マシンで並列実行させる(現時点で行うなら、Jenkinsのスレーブを複数起動させてそれぞれ別のテストケースを実行させる。→Jenkinsでなくフレームワークでやりたい)
・Cloud Testing(AWSと連携)
#これは目から鱗。確かにテストケースが違えば並列実行できるはずで、今はクラウドで一時的に大量の(仮想)マシンを借りることが出来るから、すごく現実的だよね!
その他の機能強化案は
・データの制約(正当な値の範囲)が決められるケースでは、チェックを自動化したい(例えばCOBOLのMOVEのような単純なデータ移送は基幹業務では多い。これは入力と出力が等しいことをチェックするだけなので、手で一々テストを書くのは面倒だし自動化できるはず。むしろテストと言うよりは、実行時に(他の要因によって)思わぬデータ更新がされていないかチェックする為のアサートを入れたい。DMDLの記述(演算子の種類)によっては制約が決められるのではないか)
・テストの仕様を追いやすくする(後から見て分かるようにする←これ同意。重要だw)
・テストデータのパターンを記述してテストデータを生成する(今はテストデータの「値」を記述している)
次に、「Asakusa CI on AWS」について。
#自分は不勉強な人間なもんだから、CI?何それ?って感じだったんだけど、聞いてみたらすごく興味深い。ソース修正→ビルド→テスト→ドキュメント生成といった一連の流れをなるべく自動化して実行するということらしい。
AsakusaFW自体の開発はAWS(Amazon EC2/S3)上で行われており、CI(継続的インテグレーション)のツールとしてJenkinsを使っている。
開発環境からGitHubへpushすると、「Post Receive URLs」というフックが動いてEC2上のJenkinsマスターに通知される。
JenkinsマスターはJenkinsスレーブを起動(別のEC2インスタンスを起動)し、スレーブがビルドを行う。そしてS3上のMavenリポジトリーやドキュメントを更新する。(MavenのアーキタイプもS3上に置かれている)
また、開発環境からpushした際やビルド結果をTwitterに送っている(@asakusa_ciというユーザー。@apirakunさんと@ashigeruさんくらいしか見てないらしいw)。
JenkinsマスターはEC2マイクロインスタンスで起動しっぱなし。Webフロントとして使っている。
Jenkinsスレーブは当初はスモールインスタンスだったが、High-CPUミディアムインスタンスを使うことで、値段は2倍になったがビルドにかかる時間は半分になった。AmazonEC2プラグインを使うことで、30分アイドルだったら(何もする事が無かったら)自動的にインスタンスが閉じる。
「Post Receive URLs」での通知はURLが固定なので、修正された対象のブランチが分からない。そこでJenkinsのプラグインを用いて変更があるブランチだけビルドしている。
ビルドもビルドジョブを分けて多段(パイプライン)で実行している。
最後に、実際のソースコードを見てみた。
テスト実行方法はどのDSLも基本的には同じ仕組み。
最初にAshigelコンパイラーを使ってコンパイルしているが、テストでは(実際の実行とは異なり、)簡易実行計画(トポロジカルソートされたもの)を使っている。
SPIによる拡張ポイントは以下の通り。
・SourceProvider(データを読み込む。拡張子を見て実装を切り替える。0.2ではJsonSourceProviderとExcelSheetSourceProvider)
・ImporterPreparator(テストデータを入力ファイルに書き込む。ImporterDescriptionの種類(ファイル・DB)に応じて実装を切り替える)
・ExporterRetriever(出力結果ファイルを読み込む)
・VerifyRuleProvider(検証ルールを読み込む)
検証ルールはModelVerifierを継承して自分で作ることも出来る。
例として、検証データをテーブルから読み込むTableSourceProvider。「bulkloader:」というスキーマのURLのときに使われるようになっている。
AsakusaFWのissuesの64番に登録されていて、0.2.2で取り込まれるらしい。
例えばHadoopへ移植する現行システムのデータと突き合わせて結果が一致しているかどうかを検証する事を想定しているらしい。なるほど、それは需要がありそう。
テストデータの読み込みとかも自作できるようになっているのは何かに使えそう。
CIについても、Jenkinsの名前は聞いたことがあったが、内容は初めて。興味深い話が聞けたものです。
ありがとうございました。
Scalaのちょいネタ。
Scalaでクラス定義のソースファイルの分割っぽいものが出来た。
まぁ、ただ単にクラス内のメソッドを別のトレイトに移して、ミックスインしただけのことなんだけど。そもそもトレイトは実装を持てるのでそういう目的に使うものだろうし。
ポイントは、トレイトから元のクラス内のメンバーにアクセスできるってことだね。自分型アノテーションまじ便利!
これを試してみようと思ったのは、クラス内の一部のメソッドだけオーバーロードを作りまくって数が多くなるので、ソース内の見通しが悪くなるから別ファイルに切り出したかったという理由。
これなら切り出したソースファイルを自作ツールで自動生成することもできるようになるので、良さそう。