かまたま日記3

プログラミングメイン、たまに日常

Selenium2(WebDriver)でFlash操作

What is Selenium(WebDriver)?

  • Webアプリケーション用テストツール。ブラウザの操作をシミュレート(自動化)して、Webアプリケーションの画面周りの再帰試験(リグレッションテスト)を実施することができる。
  • 提供されているWebDriver( ver2.21.0時点 )
    • InternetExplorerDriver
    • FirefoxDriver
    • ChromeDriver
    • SafariDriver
    • IPhoneDriver
    • IPhoneSimulatorDriver
    • AndroidDriver
    • AndroidWebDriver
    • EventFiringWebDriver
    • HtmlUnitDriver
  • Selenium2.0よりWebDriverが統合されていろいろ便利になったみたい。

SeleniumFlashが扱えるの?

Selenium単体ではFlashが扱えないようです。
調べてみた結果flash-seleniumっていうライブラリを見つけましたがSelenium1系にしか対応していません。

Selenium公式サイトにWebDriverからSeleniumインスタンスを生成できる方法が書いてあったので、それを試してみます。

flash-seleniumのサンプルでのsetUpを書き換えるとこんな感じ

	private WebDriver driver;
	private FlashSelenium flashApp;
	private Selenium selenium;
	…
	public void setUp() {
		driver = new FirefoxDriver();
		selenium = new WebDriverBackedSelenium(driver, URL);
		selenium.open(URL);
		flashApp = new FlashSelenium(selenium, "clickcolors");
		assertEquals(100, flashApp.PercentLoaded());
	}
	…

でもこれだとPercentLoaded()が失敗します。
WebDriverとSeleniumでのCommandProcessorの違い(WebDriverCommandProcessorとHttpCommandProcessor)のため
単純にWebDriverBackedSeleniumを使っただけではFlashSeleniumは使えないようです。

自分で作っちゃおう

FlashSeleniumがそのまま使えなかったので、FlashSeleniumを参考に自分でDriverを作ってみました。

public interface IFlashWebDriver {
	Object call(String paramString, String[] paramArrayOfString);
	int percentLoaded();
}
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class FlashWebDriver implements IFlashWebDriver {
	
	private WebDriver driver;
	private WebElement flashElement;
	
	public FlashWebDriver(WebDriver driver, String flashObjectId) {
		this.driver = driver;
		this.flashElement = driver.findElement(By.id(flashObjectId));
	}

	public Object call(String paramString, String[] paramArrayOfString) {
		return ((JavascriptExecutor) driver).executeScript(
				"return arguments[0]."+jsForFunction(paramString, paramArrayOfString),
				flashElement
			);
	}

	String jsForFunction(String functionName, String[] args) {
		String functionArgs = "";
		if (args.length > 0) {
			for (int i = 0; i < args.length; ++i) {
			functionArgs = functionArgs + "'" + args[i] + "',";
		}

		functionArgs = functionArgs.substring(0, functionArgs.length() - 1);
		}
		return functionName + "(" + functionArgs + ");";
	}

	public int percentLoaded() {
		// return as long
		long percentLoaded = (Long)call("PercentLoaded", new String[0]);
		return (int)percentLoaded;
	}
}

Flash操作の仕組み自体はJavaScriptを使ってFlashメソッドをcallするというシンプルなものなので
ここを参考に、JavaScriptの実行方法をWebDriver用に修正しました。

使い方はこんな感じ

	private WebDriver driver;

	…
	public void setUp() {
		driver = new FirefoxDriver();
		IFlashWebDriver flashApp = new FlashWebDriver (selenium, "clickcolors");
		assertEquals(100, flashApp.percentLoaded());
	}
	…

まだpercentLoaded()メソッドしか移行できていないので、FlashSeleniumの他のメソッドも移行したいです。