Webのユニットテスト② Java

久々の再開です。前回の続きです。
SampleFormのテストを簡単にする為にユーティリティクラスを作ってみます。


WebアプリケーションのテストはSeleniumを使ってテストしてみます。

WebTester.java

SeleniumServerを起動し、Seleniumインスタンスを生成します。
Seleniumインスタンスを使って、ブラウザを操作しながらテストしていきます。

package sample;

import java.util.Properties;

import org.openqa.selenium.server.SeleniumServer;

import com.thoughtworks.selenium.DefaultSelenium;
import com.thoughtworks.selenium.Selenium;

public class WebTester {

  private Properties prop;
  private SeleniumServer seleniumServer;
  private Selenium selenium;

  public void setUp() throws Throwable {

    // プロパティファイル読み込み
    if (this.prop == null) {
      this.prop = new Properties();
      this.prop.load(this.getClass().getResourceAsStream("/WebTester.properties"));
    }

    // テスト対象のサーバURL&ブラウザ設定をプロパティから読み込む
    String url = this.prop.getProperty("SeleniumTest.Url");
    String browser = this.prop.getProperty("SeleniumTest.Browser");

    // SeleniumServerを起動する
    this.seleniumServer = new SeleniumServer();
    this.seleniumServer.start();

    // seleniumインスタンス起動
    this.selenium = new DefaultSelenium("localhost", this.seleniumServer.getPort(), browser, url);
    this.selenium.start();
  }

  public void tearDown() throws Throwable {

    // Seleniumインスタンスを停止
    this.selenium.stop();
    // SeleniumServerを停止
    this.seleniumServer.stop();
  }

  public Selenium getSelenium() {
    return this.selenium;
  }

  public String getWebAppName() {
    return this.prop.getProperty("SeleniumTest.App");
  }
}

WebTester.properties

WebTesterで使用するプロパティを定義しています。
他のブラウザでのテストも簡単に行えるように、定義情報を外だしにしておきます。

# テスト対象サーバのURL
SeleniumTest.Url=http://localhost:8080/

# テスト対象のWEBアプリケーション名
SeleniumTest.App=HelloApacheClick

# テストで使用するブラウザ
SeleniumTest.Browser=*iexplore
#SeleniumTest.Browser=*firefox

HtmlTableAssert.java

指定されたHTMLテーブルの行数、列数、表示値をアサートするクラスです。
Seleniumにありそうなクラスですが、ないみたいなので作ってみました。


SeleniumではHTMLの要素をXPATHで指定します。
例えば、class名がitsというtableの1行2列目にある要素を指定したい場合は、

xpath=//table[@class='its']//tr[1]/td[2]

となります。

package sample;

import org.junit.Assert;

import com.thoughtworks.selenium.Selenium;

public class HtmlTableAssert {

  private HtmlTableAssert() {
  }

  // テーブルの表示データを確認
  public static void assertEquals(Selenium selenium, String tablePath, String[][] expected) {

    for (int i = 0; i < expected.length; i++) {

      // 比較対象の行が存在するか
      if (!selenium.isElementPresent(getRow(tablePath, i))) {
        Assert.fail("Different number of Rows : " + expected.length + " : " + (i + 1));
      }

      for (int j = 0; j < expected[i].length; j++) {

        // 比較対象の列が存在するか
        if (!selenium.isElementPresent(getColumn(tablePath, i, j))) {
          Assert.fail("Different number of columns : " + expected[i].length + " : " + (j + 1));
        }

        // 列の表示値を確認
        String actual = selenium.getText(getColumn(tablePath, i, j));
        Assert.assertEquals("Difference on row:" + (i + 1) + ", column:" + expected[i][j], expected[i][j], actual);
      }

      // 比較対象の列数が期待値を超えていないか
      if (selenium.isElementPresent(getColumn(tablePath, i, expected[i].length))) {
        Assert.fail("Over number of columns : " + expected[i].length);
      }
    }

    // 比較対象の行数が期待値を超えていないか
    if (selenium.isElementPresent(getRow(tablePath, expected.length))) {
      Assert.fail("Over number of rows : " + expected.length);
    }
  }

  private static String getRow(String tablePath, int row) {
    return "xpath=//" + tablePath + "//tr[" + (row + 1) + "]";
  }

  private static String getColumn(String tablePath, int row, int column) {
    return getRow(tablePath, row) + "/td[" + (column + 1) + "]";
  }

}