Java Advent Calendar 2015と JavaFX Advent Calendar 2015の10日目の記事です。
昨日は下記のお二人でした。
- Java Advent Calendarは@namihira_kさんの 「パフォーマンスを意識したJavaコーディング」
- JavaFX Advent Calendarは@skrbさんの 「Interpolator で補間」
明日は下記のお二人です。
- Java Advent Calendarは@bitter_foxさん
- JavaFX Advent Calendarは@y_q1mさん
TestFXを知る
先月ダウンロードしたJava Magazine vol23に面白い記事が載っていました。 テストについて特集された中の、TestFXによるJavaFXのテストについての記事です。 TestFXはJavaFXのユーザ・インターフェースをJUnitベースでテストするためのAPIということで、 JUnitで書いたロジック通りにユーザ・インターフェースのテストが実施されます。 単純にロジックをなぞるだけではなく、実際にユーザ・インターフェースを操作した結果を判定してくれるようです。 これは、実際にテストを実行した際に、JavaFXのアプリ上でマウスカーソルが自動的に動いてボタンをクリックしたりすることからもわかります。
普段のプロジェクトでは、残念ながらJavaFXではなくFlexを使っているのですが、 ユーザ・インターフェース周りのテストの仕組みはあってもなかなか思ったようなテストができていないのが現実です。 TestFXはJUnitの延長上でテストができそうなので期待できそうです。
内容を説明する前に、実際に実行した際の動画を記録しました。 動画だと自動で動いているのかわからないと思いますが、 テスト起動後には何も操作をしていません。
アプリの説明
テストに使ったアプリは、ラベルとボタンのあるシンプルなものです。 ボタンをクリックすることで、ラベルに「Hello World!」と表示します。
実際のコードは下記にあります。
https://github.com/kokuzawa/javafx-test
TestFXを設定
Mavenプロジェクトでは下記のDependencyを追加します。
<dependency>
<groupId>org.loadui</groupId>
<artifactId>testFx</artifactId>
<version>3.1.2</version>
<scope>test</scope>
</dependency>
テストを書く
対象のテストクラスは、TestFXを使うためにorg.loadui.testfx.GuiTest
クラスを継承します。
org.loadui.testfx.GuiTest
クラスはgetRootNode()
メソッドを持ち、そのメソッドでテストしたい画面のFXMLをロードします。
package org.katsumi;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Parent;
import org.junit.Test;
import org.loadui.testfx.GuiTest;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.junit.Assert.assertThat;
import static org.loadui.testfx.controls.Commons.hasText;
public class IndexControllerTest extends GuiTest
{
@Override
protected Parent getRootNode()
{
try {
return FXMLLoader.load(getClass().getResource("index.fxml"));
}
catch (IOException e) {
Logger.getLogger(IndexControllerTest.class.getName()).log(Level.SEVERE, "", e);
return null;
}
}
@Test
public void testSay()
{
final Node node = find("#button");
click(node);
assertThat("#greeting", hasText("Hello World!"));
}
}
テストメソッドは普通にJUnitの形式です。
内容ですが、まずfind("#button")
でfx:idがbuttonのコントロールを見つけます。
見つけたボタンコントロールをclick
メソッドを利用して実際にクリックします。
ラベルに「Hello World!」が設定されたことをAssert.assertThat
で検証します。
まとめ
TestFXはJUnitベースなので抵抗なくテストを実装することができました。 ただ、連続で何度か実行しているとエラーになることがありました。 原因を調べているのですが、まだちょっとわからない状態です。 とは言っても、エラーになるのは稀で、基本的は正常に動作します。
テストコードの導入はプロジェクトの最初の頃に決めておかないと、プロダクトコードがテストしにくい形で作られてしまうことが多々あります。 特にクライアント側のコードはその傾向が強いと思いますので、もしこれからJavaFXのプロジェクトを始める際のであれば、 TestFXの導入を検討してみてはいかがでしょうか。
今回この記事を書くきっかけになった、Java Magazineは下記からダウンロードすることができます。 http://www.oracle.com/technetwork/jp/articles/java/overview/index.html?elq_mid=33486&sh=1612166126426151606143&cmid=JPFM15040092MPP006C005