FEST-SwingでGoos本を写経したときのwork-around
Goos本ではGUIのテスティングツールとしてwindowlickerを使用していますが、導入に際してビルドが通らず、写経のためだけに使うのも嫌だなということでFEST-Swingを使うことにしました。
ところが、FEST-Swingでは「ラベルに表示された文字列が変更されたらその文字列をチェックしろ」といったことはできません*1。
そこでとったwork-aroundのコードが下記になります(抜粋なのでこれだけでは動きません)。
public class AuctionSniperDriver { private FrameFixture fixture; // どこかで初期化する public void showsSniperStatus(String statusText) throws InterruptedException { for (int i=0; i<10; i++) { try { fixture.label().requireText(statusText); } catch (AssertionError ex) { if (i==10) throw ex; // リトライの上限に達したらテスト失敗と判断 Thread.sleep(200); // 200msのインターバルを設ける continue; // 失敗したらもう一度 } break; // テストに成功するとここに到達する } } }
つまり、requireText
が失敗すればAssertionError
が投げられるので、成功するか上限(ここでは2秒)に達するまでやり直すという方法になります。
200ms以内にラベルの文字列が変わってしまうことは、おそらくないという想定です。
誰向けの情報だよという感じですが、考えるのにちょっと時間がかかってしまったのでメモしておきました。
*1:windowlickerでどうしてるのか?ということを調べるの含めて、今後役に立たないだろうと思ってやっていません
FEST-Swingを使う (2) - すでに起動されたウィンドウを使用する場合のテンプレート
< (1) テスト内でウィンドウを起動する場合のテンプレート
1. 概要
前回はテスト内でウィンドウを起動したため、ウィンドウのインスタンスをFrameFixture
のコンストラクタに渡すことができました。
しかし、End-to-Endテストなどで直接インスタンスが取得できない場合があります。 今回はこういった場合に、既に起動されているウィンドウからテスト対象ウィンドウを取得する方法を紹介します。
2. サンプル
LabelWindow.java:ラベルにHelloと表示するウィンドウ(前回と同じなので割愛)
LaunchLabelWindow.java:LabelWindowを起動
LaunchLabelWindowTest.java:起動されたLabelWindowでラベルがHelloであるかをテストする
// LaunchLabelWindow.java package festsample; public class LaunchLabelWindow { public static void Launch() { new LabelWindow(); } }
// LaunchLabelWindowTest.java package festsample; import org.fest.swing.core.BasicRobot; import org.fest.swing.finder.WindowFinder; import org.fest.swing.fixture.FrameFixture; import org.junit.After; import org.junit.Test; import org.junit.Before; public class LaunchLabelWindowTest { private FrameFixture fixture; @Before public void before() { // ウィンドウが外部で起動される LaunchLabelWindow.Launch(); // 名前が"Label-Window"のウィンドウを、1秒以内に探す fixture = WindowFinder .findFrame("Label-Window") .withTimeout(1000) .using(BasicRobot.robotWithCurrentAwtHierarchy()); } @After public void after() { fixture.cleanUp(); } @Test public void 起動中のLabelWindowにHelloが表示されていること() { fixture.label("label1").requireText("Hello"); } }
before()
のfindFrame
の引数でウィンドウの名前を指定します*1。
withTimeout
は探す時間のタイムアウト時間(ミリ秒)です。
前回と比べるとEDTセーフな記述がなくなっている分、コードが短くなっています。
見つからなかった場合
指定した名前のウィンドウが表示されていない(名前が間違っている)といった理由でfindFrame
がタイムアウトした場合、次のようなエラーメッセージが表示されます。
Timed out waiting for component to be found using matcher org.fest.swing.core.NameMatcher[name='Label-Window', type=java.awt.Frame, requireShowing=true] Unable to find component using matcher org.fest.swing.core.NameMatcher[name='Label-Window', type=java.awt.Frame, requireShowing=true].
[]内がFESTの想定している条件なので、これをたよりにデバッグしてください。
3. 参考
http://docs.codehaus.org/display/FEST/Testing+Long-Duration+Tasks
http://docs.codehaus.org/display/FEST/Looking+up+Components+with+ComponentFinder
FEST-Swingを使う (1) - テスト内でウィンドウを起動する場合のテンプレート
(2) すでに起動されたウィンドウを使用する場合のテンプレート >
1. 概要
FEST-SwingはJavaのGUIツールキットであるSwingのテスティングツールです。
今回は、そのテンプレートをメモします。
2. サンプル
[テスト対象]
LabelWindow.java :"Hello"と書かれたラベルを表示するウィンドウ
[テスト]
LabelWindowTest.java:「文字列"Hello"が表示されているか」をテストします
// LabelWindow.java package festsample; import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.JLabel; /** LabelにHelloと表示するウィンドウ */ public class LabelWindow extends JFrame { private JLabel label; public LabelWindow() { label = new JLabel("Hello"); label.setName("label1"); add(label, BorderLayout.NORTH); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(200, 100); setName("Label-Window"); setVisible(true); } }
// LabelWindowTest.java package festsample; import org.fest.swing.edt.FailOnThreadViolationRepaintManager; import org.fest.swing.edt.GuiActionRunner; import org.fest.swing.edt.GuiQuery; import org.fest.swing.fixture.FrameFixture; import org.junit.After; import org.junit.Test; import org.junit.Before; import org.junit.BeforeClass; public class LabelWindowTest { private FrameFixture fixture; @BeforeClass public static void beforeClass() { FailOnThreadViolationRepaintManager.install(); } @Before public void before() { // 新たにウィンドウを作成する LabelWindow window = GuiActionRunner.execute(new GuiQuery<LabelWindow>() { @Override protected LabelWindow executeInEDT() throws Throwable { return new LabelWindow(); } }); fixture = new FrameFixture(window); fixture.show(); } @After public void after() { fixture.cleanUp(); } @Test public void ラベルがHelloであること() { fixture.label("label1").requireText("Hello"); } }
@BeforeClass
・@Before
・@After
には、Swingのスレッドに関するルールを守る上で必要な処理が記述されています。*1。
別のウィンドウをテスト対象にするにはLabelWindow
をnewしている行(とテストケース)を書き換えます。
テスト自体は@Test
に書かれた一行だけです。label
で引数に指定した名前(setTextで設定したもの)のラベルを取得し、requireText
でラベルに表示されているべき文字列をassertしています。
3. 参考
インストール方法:http://d.hatena.ne.jp/torutk/20110130/p1
テストコード:http://docs.codehaus.org/display/FEST/Getting+Started