unit testing javascript with junit/javafx
Post on 15-Jan-2015
6.507 Views
Preview:
DESCRIPTION
TRANSCRIPT
JUnitでJavaScript
テスト
Fx-Js-JUnitの紹介
おことわり
● この発表ではJavaFXの話はほとんど出てきません。
● JavaScriptの話を延々とします。
● あらかじめご了承下さい。
誰?
● 名前 : @mike_neck● 所属 : 無職
○ 1日9時間勤務で18時定時で昼1時間の休憩に加えて3時間昼寝できる会社探しています。
● 職業 : プログラマー○ Groovy / JavaScript / Java
● ブログ○ mike、mikeなるままに…
本日のテーマ
● JavaでJavaScriptをテストする○ Fx-Js-JUnitの紹介○ 技術接近遭遇、的な○ 名状しがたい…
ところで…
JavaScriptのテストどう
していますか?
QUnitjQueryのテストでも使われているシンプルかつ強力なテストフレームワーク。Phantom.jsでCUIから操作可能。JavaScriptでテストを記述。
Seleniumブラウザーの自動操作ツール。Selenium Web Driverを用いてUI系のテストが記述できる。画面がボコボコ立ち上がるのがうざい。
JavaでJavaScriptのテス
トが書けて、かつうざくな
い奴が欲しいと思いませ
ん?
そこでFx-Js-JUnitで
すよ!
Fx-Js-JUnitを三行で
説明せよ!
Fx-Js-JUnitを三行で説明せよ!
● JavaFX2.0のWebEngineを用いたテストツール。
● JUnitで型安全にJavaScriptのテストができる。
● ブラウザーが立ち上がらないのでうざくない!
…ニャル子、あかちゃんつくろ
そうそう、JUnitの説明は
省きますよ
詳しくはWeb + DB プレス
#69のJUnit特集で
JUnit
Server JavaFX
Test
サンプルテストコード
@ClassRuleprivate static UseFxJsJUnit fxJsJUnit = UseFxJsJUnit .address('http://www.google.com') .identifiedBy('TestClass').get();
private JsJUnit jsJUnit;
@Beforepublic void setUp () { jsJUnit = fxJsJUnit.getTester();}
@ClassRuleでテスト前にJavaFXアプリケーションを起動
JavaScriptのインターフェースを取得
サンプルテストコード
@Testpublic void longTest () { assertThat(jsJUnit.callLong(Integer.MAX_VALUE + " + 1"), is (Integer.MAX_VALUE + 1L));}@Testpublic void personTest () { Person person = new Person(); person.setName("mike"); person.setAge(35); assertThat(jsJUnit.callAs("{name : 'mike', age : '35'}", Person.class), is (person));}
型Longを期待するテスト実行
型Personを期待するテスト実行
Fx-Js-JUnitJavaScriptのテストが
カターンゼン
型安全
Fx-Js-JUnit< `・ω・´ > ヨロシク
The End
…
……
………
すんません
調子こきました
技術
JavaScriptを型安全に取り扱うために
● JavaFXスレッドの理解● 並列処理を構成する部材の
理解● JavaScriptオブジェクトから
Javaオブジェクトへのマッピング
JavaFXスレッドの理解-1
● アプリケーションを起動した後の部分のコードはアプリケーション終了後に実行される
↑Platform.exit(); の後に実行される。
Application.launch(App.class);doSomething();
JavaFXスレッドの理解-2
● UIを構成するオブジェクトへの操作、結果の取得はJavaFXスレッドを介する必要がある。
WebEngine engine;
engine.executeScript("1 + 1");
Platform.runLater( { engine.executeScript("1 + 1");});
JavaFXスレッドの理解-3
● UIを構成するオブジェクトはJavaFXスレッド上で生成しなければならない
JavaFX Threadengine = new WebEngine();
Main ThreadWebEngine engine;
WebEngine
JavaFXスレッドの理解-まとめ
● JUnitからWebViewを操作するために
○ JUnitとは別のスレッドからJavaFXアプリケー
ションを起動
○ 別のスレッドに演算させた結果を待機して、
取得
○ JUnitはJavaFXスレッドでインスタンス化され
たオブジェクトへの参照を取得
並列処理を構成する部材の理解
● java.util.concurrent.ExecutorService○ 別スレッドの処理を簡易に記述○ JavaFXアプリケーションの起動にも
ちいる● java.util.concurrent.BlockingQueue<T>
○ JavaFXスレッドからのメッセージング(値のやり取り)に使用する
● javafx.application.Platform○ JavaFXへの操作を提供
並列処理を構成する部材の理解
詳しい話は下記の書籍を参照。
Java並行処理プログラミング
3,990JPYくらい。
http://goo.gl/UUzc1
JS→Javaマッピング
WebEngineのAPIよりhttp://docs.oracle.com/javafx/2/api/javafx/scene/web/WebEngine.html
JavaScript values are represented using the obvious Java classes: null becomes Java null; a boolean becomes a java.lang.Boolean; and a string becomes a java.lang.String. A number can be java.lang.Double or a java.lang.Integer, depending...If the result is a JavaScript object, it is wrapped as an instance of the netscape.javascript.JSObject
JS→Javaマッピング
JavaScript Object
typeof value
Java Object
null object null
false boolean java.lang.Boolean
23 number java.lang.Integer
1.10 number java.lang.Double
"script" string java.lang.String
JS→Javaマッピング
WebEngineのAPIよりhttp://docs.oracle.com/javafx/2/api/javafx/scene/web/WebEngine.html
JavaScript values are represented using the obvious Java classes: null becomes Java null; a boolean becomes a java.lang.Boolean; and a string becomes a java.lang.String. A number can be java.lang.Double or a java.lang.Integer, depending...If the result is a JavaScript object, it is wrapped as an instance of the netscape.javascript.JSObject
JS→Javaマッピング
┌(┌ ^o^)┐ JSObject...
JS→Javaマッピング
Plain Old JavaScript Object (POJSO)なら
JSObject#getMember()でマッピングが可能
{name : "cthuga", str : 80, con : 120, siz : 140, pow : 42}
JSObject cthuga = ...;assertThat( (String)cthuga.getMember("name"), is ("cthuga") );
JS→Javaマッピング
SAN値を減少させるオブジェクト…
JS→Javaマッピング
JSObject date = ...;date.getMember("year");
JSExceptionが発生する
Dateオブジェクト…
JS→Javaオブジェクト
JavaScriptのDateオブジェクトにはメソッドはあるが、メンバーは存在しない。
←Dateオブジェクトにはメンバーがない
←POJSO
JS→Javaマッピング
ちなみにJavaScriptでちゃんとメンバーの隠蔽化がなされたオブジェクト…var Encapsulation = function() {
var count = 0;this.addAndGet = function () {
count ++;return count;
}};var counter = new Encapsulation();return counter;
JS→Javaマッピング
そういったオブジェクトもメンバーを持ちません。
JS→Javaマッピング
メンバーのないJSObjectをPOJOにマッピングするいい方法はないか
JS→Javaマッピング
メソッドと戻り値の型情報がわかれば大丈夫だ、問題ない
テストしたい関数
JS→Javaマッピング
関数を実行する関数を作成
JS→Javaマッピング
関数を実行する関数を実行
JS→Javaマッピング
関数を実行する関数を実行する関数を作る
JS→Javaマッピング
{…}を無名関数化
JS→Javaマッピング
戻り値を既知のメソッドでPOJSO化
JS→Javaマッピング
テスト実行
JS→Javaマッピング
既知の型、メンバーを持つPOJSOを取得
JS→Javaマッピング
(int) jsObject.getMember("addAndGet");
JS→Javaマッピング
DateはPOJSOにマッピング
既知の型とメソッドはアノテーションに記述
JS→Javaマッピング
型安全に実行してassertionできる!
JS→Javaマッピング
JS→Javaマッピング
equals(java.lang.Object)とhashCode()メソッドの実装は自己責任でね★
JS→Javaマッピング
● プリミティブ型は直接取得してassert● POJSOはgetMemberメソッド経由で
POJOにマッピングしてassert● 特殊なオブジェクトはアノテーションのメ
タ情報からPOJSOを経由してマッピングしてassert
Fx-Js-JUnitJavaScriptのテストが
カターンゼン
型安全
Enjoy JavaScript!
ご静聴ありがとぉ…
…ぉ?
テストは複数同時に実行
したいですよねぇ
お望みであれば
やってみせますが…
名状しがたい…
SAN値が下がりますよdef service = Executors.newThreadPool(2)service.execute {
Application.launch(App) }service.execute {
Application.launch(App) }
名状しがたい…
名状しがたい…
名状しがたい…
複数 + JavaFX で検索
名状しがたい…
名状しがたい…
JavaFXは二度起動させることはできぬ!
名状しがたい…
● 複数のテストへの対応○ WebEngineを複数立ち上げる○ 定期的にポーリングを行なって、
WebEngineが利用されなくなったら終了する
名状しがたい…
● TODOs○ 複数のテストへの対応○ ServletコンテナまたはJavaEEコン
テナの搭載○ GitHubへの公開
○ Maven/Ivyレポジトリーへの登録○ 他ご要望がありましたら
@mike_neckまで
Thank youfor your attention
top related