hatenob

プログラムって分からないことだらけ

一人Web開発~第12夜 Integration Test

Integration Test(以下、IT)は日本語にすると結合テストなんだけれども、何と何を結合するのかでだいぶんテストの内容が変わってきます。
今回は大きくこの2つをITとして取り扱うことにします。

  • アプリケーションを画面から実行するテスト。だいたい1つのイベントを1つのテストにする。
  • インフラレベルの構成を挙動として確認するテスト。

まずは前者から取り組みます。

テスト設計

と言っても、画面1つしか作ってないので設計も何もない。

  1. トップページを開く
  2. 入力項目を入力する
  3. 登録ボタンを押す
  4. 成功メッセージが表示される

こんな画面操作をテストします。

テスト実装

Seleniumを使ってブラウザを起動してテスト、としたかったのだけれど、selenium 2.40.0、Firefox 27.0.1の環境でなぜかエラーになってうまくいかなかった。

org.openqa.selenium.firefox.NotConnectedException: Unable to connect to host 127.0.0.1 on port 7055 after 45000 ms

port7055に接続できないと言っており、確かにこのときnetstat見てもSYN_SENT状態で受け口がない状態の模様。なんでだろうか?パーソナルファイアウォールを無効にしたり色々試したり調べたりしてみたけれども解消できず。これの調査で貴重な週末や夜のお勉強時間を使いっぱなし。先に進めたいのでFirefoxDriver使わずに、HtmlUnitDriverでブラウザ起動せずテストする方針に変更しました。そのほうがGUI環境のないサーバでもテストできるからね、と。HtmlUnitであればSelenium不要なのだけれど、今後動くようになったらDriver変えるだけで済むからね、とか。

Mavenプロジェクトとして、IT用のプロジェクトを別に作りました。アプリに含めてもいいのだけれども、アプリのプロジェクト内にいるとどうも1つの画面と1つのテストクラスを紐づけないといけないような気がして窮屈なので、別にすることにしました。パッケージ名も、アプリのパッケージ名を全く意識せずに済むので精神衛生上よろしいです。

テストコードは先のアクション通りに実施するだけ。

public class CustomerTest {

	private WebDriver driver;

	@Before
	public void setUp() {
		driver = new HtmlUnitDriver(false);
		driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
	}

	@After
	public void tearDown() {
		driver.quit();
	}

	private static final String URL_TOP = "http://localhost:8080/oneman/";

	private void openTop() {
		driver.get(URL_TOP);

		assertThat(driver.getTitle(), is("oneman-web"));
	}

	private void viewCustomerRegister() {
		driver.findElement(By.id("register")).click();

		assertThat(driver.getTitle(), is("Customer - register"));
	}

	private void inputCustomerRegister(String name, String password) {
		driver.findElement(By.id("name")).sendKeys(name);
		driver.findElement(By.id("password")).sendKeys(password);
		driver.findElement(By.id("register")).click();
	}

	private void assertResult(String expected) {
		assertThat(driver.findElement(By.id("result")).getText(), is(expected));
	}

	@Test
	public void should_register_a_customer() {
		openTop();
		viewCustomerRegister();
		inputCustomerRegister("tarou", "Pass123");

		assertResult("Success");
	}

}

画面上の要素にアクセスする時にidがないと何かと不便なので、画面側のタグのいつかにid属性を追加しました。
これでMavenからテストして確認。
この処理ではDBに登録をしているので、DBに登録されたことまで本当は確認したいのだけれど、今はまだここまで。

Jenkinsでは、util→ejb→webとUT実施し正常にデプロイされたあとに実施するテストとして定義してやります。

次はインフラのテスト。