daybreaksnow's diary

私を私と呼びたい

[GWT]Seleniumで非同期処理のテストを行う

GWT(gwt-dev)とSelenium(selenium-server)を同じビルドパスに入れると、内部jarでバージョンの競合が起きた([GWT]Seleniumを同一プロジェクトで動かそうとして諦めた調査ログ - daybreaksnow's diary)ので、別プロジェクトでSeleniumを動かすことにした。

ソースコードの準備

参考URL:java - GWT id element is changing every time in selenium - Stack Overflow
Seleniumから簡単に部品を取得するため、部品にIDを設定する。

1.IDを付けたい部品のensureDebugIdメソッドを呼び、IDを指定

sendButton.ensureDebugId("sendButtonId");

2.gwt.xmlで以下の要素を追加

<inherits name="com.google.gwt.user.Debug"/>

上記により、対象部品のIDが"「UIObject.DEBUG_ID_PREFIX(gwt-debug-)」+指定したID"となる。
(上記例ではgwt-debug-sendButtonIdになる)

このIDはgwt.xmlからinherits Debugタグを抜くと生成されなくなるので、本番環境への影響はない。

Seleniumの準備

参考URL:MograBlog: Running Selenium With GWT Dev
FireFoxでテストをする。
通常のSeleniumと同じようにnew FireFoxDriver()などとやっても、GWT-DEVプラグインが読み込まれず、開発モードで動作しない。

以下からFireFoxのバージョンに合わせたプラグインをダウンロードして、適当な場所に配置。
https://code.google.com/p/google-web-toolkit/downloads/list?can=2&q=xpi

ドライバ作成時にプラグインのパスを指定したFireFoxProfileを渡すようにする。

FirefoxProfile profile = new FirefoxProfile();
final String gwtPluginPath = "lib/gwt-dev-plugin-1-19-rc.xpi"; 
profile.addExtension(new File( gwtPluginPath));
driver = new FirefoxDriver( profile );
サンプル(同期実行)

普通のSeleniumと同じ

@Test
public void testSync() {
	//本番モードでテストしたいなら?以降を除去
	String pathToGwtApp = "http://127.0.0.1:8888/StockWatcher.html?gwt.codesvr=127.0.0.1:9997";
	driver.get(pathToGwtApp);

	WebElement sendButton = driver.findElement(By.id("gwt-debug-sendButtonId"));
	sendButton.click();

	WebElement sendResultLabel = driver.findElement(By.id("gwt-debug-sendResultLabelId"));
	assertThat(sendResultLabel.getText(), equalTo("fail"));
}
サンプル(非同期実行)

参考URL:Selenium - Google Web Toolkit Examples
ボタンクリック時に非同期処理がある場合(RPCコール)、コールバックメソッドが終わるまで待つ。

@Test
public void testAsync(){
	driver.get(pathToTest);
	
	WebElement sendButton = driver.findElement(By.id("gwt-debug-sendButtonId"));
	assertThat(sendButton.isEnabled(), is(true));
	//リスナでRPC呼び出しが行われるボタンをクリック
	sendButton.click();
	//レスポンスが返ってくるまではボタンが無効化される想定
	assertThat(sendButton.isEnabled(), is(false));

	// DEFAULT_SLEEP_TIMEOUT(500ms)毎にapplyが評価される。10秒立っても終わらなったら例外を投げる
	new WebDriverWait(driver, 10).until(new ExpectedCondition<Boolean>() {
		public Boolean apply(WebDriver d) {
			// ボタンが有効化される(レスポンスが返ってくる)まで待つ
			WebElement sendButton = driver.findElement(By.id("gwt-debug-sendButtonId"));
			return sendButton.isEnabled();
		}
	});
	
	//レスポンスによって変化した部品を評価
	WebElement sendResultLabel = driver.findElement(By.id("gwt-debug-sendResultLabelId"));
	assertThat(sendResultLabel.getText(), is("fail"));
}