Seleniumひとめぐり(FireFox)

Seleniumには色々な機能があるがSeleniumIDEしか使ったことがなかったので、その他の機能を使ってみた。業務で使うことを考えるとIEを克服?しないといけないのだが、なぜか自宅のPC(Vista)ではIEが安定稼動しないので、今回はFireFoxのみとした。

参考URL:
@IT
http://www.atmarkit.co.jp/fjava/rensai4/devtool07/devtool07_1.html
本家
http://seleniumhq.org/

今回試した機能(プロジェクト):


Selenium RC◆
Selenium RCにも色々な機能があるのだろうが、今回はTestSuiteをコマンドラインから実行するという部分に絞った。

・まずは、SeleniumIDEの操作記録機能でTestCase、TestSuiteを作成する。
Selenium RCは、ここ(のSelenium Server (formerly the Selenium RC Server))からダウンロードする。
・コマンドの説明は、前述の@ITの記事にもあるので詳細は書かないが、ここでは、以下のようなコマンドを入力した。

java -jar selenium-server-standalone-2.13.0.jar -htmlSuite *firefox http://localhost:8080/finance/ c:\practice\grails\finance\testsuite.html result01.html

testsuite.htmlというのがSeleniumIDEで作成したTestSuiteで、result01.htmlはテスト結果の出力先。

感想:
firefoxの部分を*chromeとか*operaとかに変えると他のブラウザでのテストができる(ハズ)だが、本日のところは残念ながらFireFoxでしか正常稼動しなかった・・・。複数ブラウザをお手軽にテストするというのが狙いだったので残念。


Selenium WebDriver◆
WebDriverを用いると、JavaRubyPythonなどからSeleniumのテストを実行することが出来る。
この中では一番馴染みがあると言う理由でJavaを選択。

・まずは、Selenium WebDriverをセットアップしたeclipseプロジェクトを作成する。
手順としては、本家のDocumentに沿って、maven2を使った。
参考 http://seleniumhq.org/docs/03_webdriver.html#setting-up-a-selenium-webdriver-project
さほど難しい英語ではないので、読めば分かると思うが、適当なフォルダに、以下の内容のpom.xmlを記述する。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>MySel20Proj</groupId>
        <artifactId>MySel20Proj</artifactId>
        <version>1.0</version>
        <dependencies>
            <dependency>
                <groupId>org.seleniumhq.selenium</groupId>
                <artifactId>selenium-java</artifactId>
                <version>2.12.0</version>
            </dependency>
        </dependencies>
</project>

そのうえで、以下のmavenコマンドを発行。

mvn clean install

Buildが成功したら、以下のコマンドでeclipseプロジェクトに変換する。

mvn eclipse:eclipse

・テストコードの作成
SeleniumIDEにより、JUnit4形式のテストコードを生成できる。
但し、このコードを実行すると、
Could not start Selenium session: You may not start more than one session at a time
というエラーが出た。
ググッた結果でこのサイトを参考にやっつけ仕事でコードを修正した。
結果のコードがこれ。(package、import宣言は省略してある)

public class TestCaseByJava2 {	
	DefaultSelenium selenium = null;
	
	@Before
	public void setUp() throws Exception {
		WebDriver driver = new FirefoxDriver();
		String baseUrl = "http://localhost:8080/";
		selenium = new DefaultSelenium(new WebDriverCommandProcessor(baseUrl, driver));
		
	}

	@Test
	public void testTestcase_java() throws Exception {
		selenium.open("/finance/");
		selenium.click("link=finance.BorrowerController");
		selenium.waitForPageToLoad("30000");
		selenium.click("link=Borrowerを新規作成");
		selenium.waitForPageToLoad("30000");
		selenium.type("id=code", "000001");
		selenium.type("id=name", "borrower_01");
		selenium.type("id=description", "test_01");
		selenium.click("id=create");
		selenium.waitForPageToLoad("30000");
		selenium.click("link=ホーム");
		selenium.waitForPageToLoad("30000");
		selenium.click("link=finance.LoanController");
		selenium.waitForPageToLoad("30000");
		selenium.click("link=Loanを新規作成");
		selenium.waitForPageToLoad("30000");
		selenium.type("id=time", "6");
		selenium.type("id=contractNumber", "L01");
		selenium.type("id=loanType", "FLAT");
		selenium.type("id=principal", "50000");
		selenium.type("id=rate", "4");
		selenium.select("id=startDate_day", "label=20");
		selenium.select("id=startDate_month", "label=11月");
		selenium.select("id=startDate_year", "label=2011");
		selenium.click("id=create");
		selenium.waitForPageToLoad("30000");
//		verifyTrue(selenium.isTextPresent("582"));
                // この入力例だと利息額が582円となるのでその値を検証している。
		assertEquals(true, selenium.isTextPresent("582"));

	}

	@After
	public void tearDown() throws Exception {
		selenium.stop();
	}
}

ここでは、DefaultSelenium というオブジェクトを使っているが、これ以外にも、WebElementというオブジェクトを操作する方法もある。詳しくは、本家のサイトのドキュメントを参照。

感想(ならびに今後の課題)
プログラミング言語からSeleniumを操作できると色々と可能性が広がる。(当たり前か)

  • テストケースのシート(Excel)などからpoiを使って操作内容を動的に生成するとか
  • DBの状態に応じて処理を切り替えたり

たぶんこの手のことは誰かが実践済みなんだろうけど。この辺りを今後リサーチしてみたい。

◆追記
WebDriver経由でJUnitのテストコードから画面キャプチャする方法を調査したので掲載しておく。
参考 http://stackoverflow.com/questions/3422262/take-a-screenshot-with-selenium-webdriver

public class TestCaseByJava2 {	
	DefaultSelenium selenium = null;
	WebDriver driver = null;
	
	@Before
	public void setUp() throws Exception {
		driver = new FirefoxDriver();
		String baseUrl = "http://localhost:8080/";
//		Selenium selenium = new WebDriverBackedSelenium(driver, baseUrl);
//		selenium.start();
		selenium = new DefaultSelenium(new WebDriverCommandProcessor(baseUrl, driver));
		
	}

	@Test
	public void testTestcase_java() throws Exception {
		
		selenium.open("/finance/");

		selenium.click("link=finance.BorrowerController");
		selenium.waitForPageToLoad("30000");
		selenium.click("link=Borrowerを新規作成");
		selenium.waitForPageToLoad("30000");
		selenium.type("id=code", "000001");
		selenium.type("id=name", "person_01");
		selenium.type("id=description", "test_01");
// captureEntirePageScreenshotが稼動しないので苦労した。。。
//		selenium.captureEntirePageScreenshot("c:/practice/grails/finance/capture01.png", "");
		captureScreenShot("c:\\practice\\grails\\finance\\capture_001.png");
	    
		selenium.click("id=create");
		selenium.waitForPageToLoad("30000");
		captureScreenShot("c:\\practice\\grails\\finance\\capture_002.png");
		
		selenium.click("link=Borrowerを新規作成");
		selenium.waitForPageToLoad("30000");
		selenium.type("id=code", "000002");
		selenium.type("id=name", "person_02");
		selenium.type("id=description", "test_02");
		captureScreenShot("c:\\practice\\grails\\finance\\capture_003.png");

		selenium.click("id=create");
		selenium.waitForPageToLoad("30000");
		captureScreenShot("c:\\practice\\grails\\finance\\capture_004.png");
		
		selenium.click("link=ホーム");
		selenium.waitForPageToLoad("30000");
		
		selenium.click("link=finance.LoanController");
		selenium.waitForPageToLoad("30000");
		selenium.click("link=Loanを新規作成");
		selenium.waitForPageToLoad("30000");
		selenium.type("id=time", "6");
		selenium.type("id=borrowerCode", "000001");
		selenium.type("id=contractNumber", "LOAN01");
		selenium.type("id=loanType", "Flat");
		selenium.type("id=principal", "50000");
		selenium.type("id=rate", "4");
		selenium.select("id=startDate_day", "label=20");
		selenium.select("id=startDate_month", "label=11月");
		selenium.select("id=startDate_year", "label=2011");
		captureScreenShot("c:\\practice\\grails\\finance\\capture_005.png");

		selenium.click("id=create");
		selenium.waitForPageToLoad("30000");
		captureScreenShot("c:\\practice\\grails\\finance\\capture_006.png");

//		verifyTrue(selenium.isTextPresent("582"));
		assertEquals(true, selenium.isTextPresent("582"));
		selenium.click("link=Loanリスト");
		selenium.waitForPageToLoad("30000");
		captureScreenShot("c:\\practice\\grails\\finance\\capture_007.png");
	}

	private void captureScreenShot(String filePath) throws IOException {
		File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
	    FileUtils.copyFile(scrFile, new File(filePath));
	}

	@After
	public void tearDown() throws Exception {
		selenium.stop();
	}
}