JavaFXを使ってWeb画面のテスト
以前にseleniumで簡単な画面のテストを実装してみたので、同じことを@skrbさんの記事JavaFX + JUnit で JavaScript のユニットテストをする その 2 - JavaFX in the Boxを参考にJavaFXで挑戦しました。
なかなか思ったように実装できなくて困っています、、、
- ★1以下の2パターンのテストを続けて実行したかったのですが、2回目の「Hello」画面をJavaFXで再度loadするところが思ったように動作しないのです。
1回目Hello Testで「Hello」画面 ->「Greeting」画面でh1に「Hello JavaFX」が設定されることをテスト
2回目おはようTestで「Hello」画面 ->「Greeting」画面でh1に「おはよう JavaFX」が設定されることをテスト
- ★2Web画面の操作をjavascriptで実装したのですが、もっと簡潔にわかりやすく実装したいのです。
- ★3JavaFX側で実装が誤っているとJUnit側のテストが待ち状態のままで終わらなくなってしまいます。
- テストクラス
public class HelloTest { private static DummyApp dummyApp; private static ExecutorService service; public HelloTest() { } @BeforeClass public static void setUpClass() throws InterruptedException { service = Executors.newFixedThreadPool(1); service.submit(new Runnable() { @Override public void run() { Application.launch(test.DummyApp.class); } }); dummyApp = DummyApp.getInstance(); } @AfterClass public static void tearDownClass() { dummyApp.shutDown(); } @Test public void hello() throws InterruptedException { Map<String, String> results = dummyApp.HelloTest("JavaFX", "0", "0"); String result = results.get("h1"); assertThat(result, is("Hello JavaFX")); // このテストはグリーンに } @Test public void おはよう() throws InterruptedException { Map<String, String> results = dummyApp.HelloTest("JavaFX", "1", "1"); String result = results.get("h1"); assertThat(result, is("おはよう JavaFX")); // ここでJavaFX側の★1のengine.loadが動作しないような・・・ } }
- JavaFX側(Web画面を操作)
public class DummyApp extends Application { private static WebEngine engine; private static DummyApp app; private static BlockingQueue<DummyApp> instance = new LinkedBlockingDeque<>(); private BlockingQueue<Map<String, String>> arguments = new LinkedBlockingDeque<>(); private BlockingQueue<Map<String, String>> results = new LinkedBlockingDeque<>(); @Override public void start(Stage primaryStage) { app = this; engine = new WebEngine(); addListner(); engine.load("http://localhost:8080/HelloSample/faces/Hello.xhtml"); } public static DummyApp getInstance() throws InterruptedException { return instance.take(); } public void shutDown() { Platform.runLater(new Runnable() { @Override public void run() { Platform.exit(); } }); } public Map<String, String> HelloTest( String name, String greetSel, String lang) throws InterruptedException { Map<String, String> params = new HashMap<>(); params.put("name", name); params.put("greetSel", greetSel); params.put("language", lang); arguments.put(params); Platform.runLater(new Runnable() { @Override public void run() { try { if (!engine.getTitle().equalsIgnoreCase("Hello")) { engine.load("http://localhost:8080/HelloSample/faces/Hello.xhtml"); // ★1ここで「おはよう」Test時に最初の画面をloadしたいのですが、、、 instance.take(); } Map<String, String> params = arguments.take(); String nameVal = params.get("name"); String selVal = params.get("greetSel"); String langVal = params.get("language"); engine.executeScript("document.getElementById('form1:name').value = '" + nameVal + "'"); // ★2この辺の処理ももっと簡潔に書ける方法がないのかな? engine.executeScript("document.getElementsByName('form1:greetSel')[" + selVal + "].checked = true"); engine.executeScript("document.getElementById('form1:language').options[" + langVal + "].selected = true"); engine.executeScript("var btn = document.getElementById('form1:greet'); btn.click();"); } catch (InterruptedException ex) { Logger.getLogger(DummyApp.class.getName()).log(Level.SEVERE, null, ex); } } }); return results.take(); } private void addListner() { engine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() { @Override public void changed(ObservableValue<? extends State> ov, State oldState, State newState) { if (newState == State.SUCCEEDED && engine.getTitle().equalsIgnoreCase("Hello")) { try { instance.put(app); } catch (InterruptedException ex) {} } if (newState == State.SUCCEEDED && engine.getTitle().equalsIgnoreCase("Greeting")) { Document doc = engine.getDocument(); NodeList nodes = doc.getElementsByTagName("H1"); Node h1Node = nodes.item(0); // ★3例えばここで「nodes.item(1)」と間違って実装するとJUnitのTestが待ち状態になってしまいます Map<String, String> result = new HashMap<>(); result.put("h1", h1Node.getTextContent()); try { results.put(result); } catch (InterruptedException ex) {} } } }); } }
実装はtomoTaka01/HelloSampleTest: JavaFX for Web Testにアップしました。
何かいい解決策があればコメントお願いします。>-