unit testing javascript with junit/javafx

Post on 15-Jan-2015

6.507 Views

Category:

Documents

3 Downloads

Preview:

Click to see full reader

DESCRIPTION

Unit Testing Framework for JavaScript with Java

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