2012年6月11日月曜日

JavaFX + JUnit で javascriptのunit testできるようにしてやるんで、これからハマっていってやんよ - 4

前回のポストから約2ヶ月半、やっとできましたよFxJsJUnit。

みけです。


ひらめき


JavaFX2.0の発表を聞いた時にWebViewがwebkitを搭載するということで、

すぐにjavascriptのテストをJavaで書けるようになると閃いて、

今年の3月くらいにとりかかりました。

桜庭さんからJavaからJavascriptを呼び出すにはjavafx.scene.web.WebEngine#executeScript(java.lang.String)を叩けばよいと聞いていたので、

実際、初回に叩いてみたわけですが

JavaFXのコンポーネントはJavaFXスレッドで立ち上げないとダメということで、挫折しました。


成功?!


その後、桜庭さんのブログエントリーで色々とアドバイスを頂いたりしました。


それを参考にしてコードを書いてみたら、テスト1つは通ったのですが、複数回のテストが実行できないという残念な結果に終わりました


スレッド、スレッド、スレッド


もともと業務SEさんで、スレッドとか興味なかったのでスレッドの制御に悩みました。

3月末頃にはコードがグダグダになってきていて、どうしようもなくなっていたようです。

この頃は何に悩んでいたかというと、

  • テストを起動→Webサーバー起動→JavaFXアプリケーションを起動という順番で実行
  • JavaFXアプリケーションが起動完了したところで、何も動かなくなる

といった状態でどのスレッドで何がどうなっているかが全く?になっていました。

JUnitとWebサーバーとJavaFXアプリケーションとWebViewと4つのスレッドの同期化を図りつつ実行していかなければならないので、

スレッドの知識がない僕には何がどうなっているのか全くわからない状態でした。


Java並行処理プログラミング


そこで、スレッドで悩まないために、Java並行処理プログラミング ―その「基盤」と「最新API」を究める―を読みました。



桜庭さんの記事にもあるように4つのスレッドの制御のためにはjava.util.concurrent.BlockingQueue>T<や、java.util.concurrent.ExecutorServiceを押さえとかないと厳しいです。

僕もこの本のお陰でBlockingQueueとかがなんとなくわかるような気がしてきました。

で、やっとうまく行った実装では次のようにスレッドを作っています。


これらのスレッドにBlockingQueueで値を受け渡しさせることで同期化を図っています。


テストコード


テストコードを書く人(ユーザー)には、これらのスレッドのあたりを意識させない(隠蔽して)ようにするのが望ましい形です。

そこで、JUnitの@ClassRuleでテストクラスの実行前に準備することで、

ユーザーにはjavascriptの呼び出しだけを提供できるようにしました。

サンプルのテストコードは次のとおりです。

JsJUnitTest.groovy



コードはGroovyで書いていますが、Javaに近い形で書いていますので、

それほど読みづらくないと思います。


テスト対象のJavascriptは次のとおりです。

test.js




技術的なこと


実は苦労話ばかり書いていて、技術的なことは何も触れてないですね。

そのあたりは、7/2(月)にある桜庭さん主催の『第7回 JavaFX 勉強会』でお話しようと思います。

まあ、JavaFXの話は殆どなしで、javascriptとスレッドの話になりそうですが…


TODO


一応スタティックなWebサーバーのjavascriptのテストが実行できるようになったわけですが、

まだまだ、javascriptのJavaにおける扱いに関して不明な点が多くありますし、全然型安全でありません。

また、ajaxなどのテストも書けませんし、DOMでassertする部分のサポートも不十分です。

さらにGitHubリポジトリーも作ってないですし、今のgradleスクリプトではMac以外では動きません( ー`дー´)キリッ

というわけで、次のような課題があります。

  • Windows/Linux対応
  • リポジトリ公開
  • javascript→POJOマッピング対応
  • function型の扱い
  • ServletコンテナもしくはJavaEEコンテナ搭載

このあたりはボチボチとやっていきたいと思います。

0 件のコメント:

コメントを投稿