検索
連載

Playの充実したテスト環境で行う5種のテストJavaの常識を変えるPlay framework入門(6)(2/3 ページ)

サーブレット/JSPを基にする重厚長大なJavaのWeb開発のイメージを変える軽量フレームワーク「Play」について解説し、Webアプリの作り方を紹介する入門連載。今回は、シンプルな単体テストに加え、ビューやコントローラ、routeファイルのテスト、ブラウザテスト、テスト用の環境設定について解説します。

PC用表示 関連情報
Share
Tweet
LINE
Hatena

ビューのテスト

 Play frameworkのテスト実行方法が分かったところで、早速第4回で作成した名前占い結果ビュー(name_result.scala.html)に対し、テストを書いてみましょう。

 名前占い結果ビューは引数として名前を受け取り、その名前を画面表示していました。今回はビューに「太郎」という名前を渡し、その名前が正しく表示されているかどうかを確かめるテストを書いてみます。

 testフォルダにViewTestクラスを作成してください 。

@(name: String)
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>名前占い結果</title>
</head>
<body>
    @name さんの今日の運勢は最高です!
    <form action="/type/1" method="GET">
        <input type="hidden" name="name" value="@name"/>
        <input type="submit" value="恋愛運"/>
    </form>
    <form action="/type/2" method="GET">
        <input type="hidden" name="name" value="@name"/>
        <input type="submit" value="金運"/>
    </form>
</body>
</html>
テストするビューのソース(再掲)
import static org.fest.assertions.Assertions.*;
import static play.test.Helpers.*;
import org.junit.Test;
import play.mvc.Content;
public class ViewTest {
	@Test
	public void testNameResultRender() {
		Content html = views.html.name_result.render("太郎");
		String htmlString = contentAsString(html);
		assertThat(htmlString).contains("太郎");
	}
}
テストコード

 なんと、たった数行でビューのテストが書けてしまいました。コードの内容を上から順番に見ていきます。

 テストメソッドの1行目では、テスト対象のビューが実際に出力する文字列を取得するために、ビュークラスのrenderメソッドを呼んでいます。

 なお、このメソッドの呼び出し方は、コントローラで結果を返す際に利用したものと全く同じものになっています。

 ビューの出力結果は、Contentインターフェイスの実装クラスとして返されます。Contentから情報を取得するには、play.test.Helpersクラスの以下のメソッドが利用できます。

メソッド 機能 返される値の例
String contentType(Content) 出力されるcontent-typeを返す text/html
String contentAsString(Content) 出力される文字列を返す <!DOCTYPE html>
<html><head>
……

 今回は、contentAsStringメソッドを用いて、出力された全てのHTMLを取得し、その中に「太郎」という文字列が含まれているかどうかを検証しています。

コントローラのテスト

 次に、UranaiクラスのshowNameResultメソッドのテストを行います。

public static Result showNameResult() {
	String[] params = { "name" };
	DynamicForm input = Form.form();
	input = input.bindFromRequest(params);
	String name = input.data().get("name"); // 入力チェック
	if (name == null || name.trim().equals("")) {
		return badRequest("名前を入力してください。");
	}
	return ok(views.html.name_result.render(name));
}
テストするコントローラのメソッドのソース(再掲)

 showNameResultメソッドでは、フォームに名前が入力されていればOKを、未入力か空文字であればBAD_REQUESTを返します。

 今回は、名前が未入力でBAD_REQUESTが返る場合と、名前が入力されていてOKが返る場合の2つをテストします。

コントローラの呼び出し

 ビューのテストの場合は、コントローラからビューを呼び出す場合と同じようにテストコードを記述できましたが、コントローラの場合は、そううまくはいきません。

 コントローラのテストの流れは以下の通りです。

  1. ダミーのアプリケーションを起動し、play runを実行した場合と同じ状態とする
  2. テスト対象のコントローラのメソッドを実行する。必要があればHTTPリクエストのモックにフォーム等の値を指定
  3. コントローラのメソッド呼び出しの結果をResultクラスのインスタンスとして受け取り、内容を検証

 まずは、名前が未入力でBAD_REQUESTが返る場合をテストしてみます。testフォルダにControllerTestクラスを作成してください。

import static org.fest.assertions.Assertions.*;
import static play.mvc.Http.Status.*;
import static play.test.Helpers.*;
import org.junit.Test;
import play.mvc.Result;
public class ControllerTest {
	@Test
	public void testShowNameResultBadResuestNoForm() {
		running(fakeApplication(), new Runnable() {
			@Override
			public void run() {
				Result result = callAction(
					controllers.routes.ref.Uranai.showNameResult()
				);
				assertThat(status(result)).isEqualTo(BAD_REQUEST);
			}
		});
	}
}
テストコード

 ビューの場合と比べると少し複雑に見えますが、実際のテストコードはシンプルです。ビューの時と同じく、上から順に見ていきます。

 まず、テストメソッドの最初で、runningメソッドを呼び出しています。このメソッド呼び出しにより、play runを実行した場合と同じ状態となり、データベースアクセス等が行えるようになります。

 runningの第1引数には、fakeApplicationメソッドを用いてデフォルトのアプリケーションクラスを渡しています。これはコントローラのテストを書くときのおまじないと思ってください。

 なお、後述しますが、ここでapplication.confの設定を上書きすることも可能です。

 第2引数には、Runningインターフェイスを実装した、テストクラスを渡します。Play frameworkがアプリケーションの準備を終わらせた後、このクラスのrunメソッドが呼び出されます。

 次に、runメソッド内のテストコードを見ていきます。1行目では、callActionメソッドを用いてテスト対象のコントローラのメソッドを実行しています。callActionメソッドの引数には、実行するコントローラのメソッドの参照クラスを渡します。この参照クラスはコンパイル時に自動生成されています。callActionでのコントローラの処理結果は、Resultインターフェイスを実装したクラスで返されます。

 Resultについても、ビューのテストの場合と同様に、play.test.Helpersクラスのメソッドを用いて値の検証を行います。

 Resultに対して利用できる主なメソッドは以下の通りです。

メソッド 機能 返される値の例
int status(Result) ステータスコードを返す 200(OK)
String contentAsString(Result) HTMLを返す <!DOCTYPE html>
<html><head>
……
String charset(Result) 文字コードを返す utf-8
String redirectLocation(Result) リダイレクト先を返す /top

 今回は、statusメソッドを使って、BAD_REQUESTが返ってくるかどうかのみをテストしています。

フォーム入力値の設定

 次に、フォームの名前が入力され、ステータスコードOKが返る場合のテストを記述してみます。

 フォームの値をコントローラに渡すためには、HTTPリクエストのモックを作成する必要があります。HTTPリクエストのモックとしては、FakeRequestクラスが用意されています。FakeRequestを使ってフォームの値を渡すコードは以下の通りです。

 ControllerTestクラスに以下のテストメソッドを追加してください。

@Test
public void testShowNameResultOk() {
	running(fakeApplication(), new Runnable() {
		@Override
		public void run() {
			Map<String,String> formValue = new HashMap<>();
			formValue.put("name", "太郎");
			Result result = callAction(
				controllers.routes.ref.Uranai.showNameResult(),
				fakeRequest().withFormUrlEncodedBody(formValue));
			assertThat(status(result)).isEqualTo(OK);
		}
	});
}

 フォームに入力される値を渡すためには、上記のように、callActionメソッドの第2引数にFakeRequestインスタンスを渡すことで実現できます。

 FakeRequestにフォーム入力値を設定するためには、withFormUrlEncodedBodyメソッドを利用します。FakeRequestについては、フォームの値以外にも、「withSession」のような「with」で始まるメソッドを使うことで、セッション領域などについても値を設定可能です。

Copyright © ITmedia, Inc. All Rights Reserved.

ページトップに戻る