Documentation

You are viewing the documentation for the 2.2.0 release in the 2.2.x series of releases. The latest stable release series is 2.4.x.

§機能テストを書く

Play は機能テストを支援するいくつかのクラスとメソッドを提供しています。それらのほとんどは play.api.test パッケージか、Helpers オブジェクトのいずれかの中から見つけることができます。

以下をインポートすることで、これらのメソッドとクラスを追加することができます:

import play.api.test._
import play.api.test.Helpers._

§FakeApplication

Play はしばしば、play.api.Play.current が提供する Application をコンテキストとして実行することを要求します:

テスト用の環境を提供するために、Play は 本番用とは異なる Global オブジェクトや追加設定、さらには追加プラグインにより設定することのできる FakeApplication クラスを提供しています。

val fakeApplicationWithGlobal = FakeApplication(withGlobal = Some(new GlobalSettings() {
  override def onStart(app: Application) { println("Hello world!") }
}))

§WithApplication

サンプルコードにアプリケーションを渡すには、WithApplication を使います。明示的に FakeApplication を渡すこともできますが、利便性のためにデフォルトの FakeApplication が提供されています。

WithApplicationAround ブロックに組み込まれているので、自身のデータで上書きすることができます。

abstract class WithDbData extends WithApplication {
  override def around[T: AsResult](t: => T): Result = super.around {
    setupData()
    t
  }

  def setupData() {
    // setup data
  }
}

"Computer model" should {

  "be retrieved by id" in new WithDbData {
    // your test code
  }
  "be retrieved by email" in new WithDbData {
    // your test code
  }
}

§WithServer

ときどき、テストコードから実際の HTTP スタックをテストしたくなりますが、このような場合は WithServer を使ってテストサーバを起動することができます。

"test server logic" in new WithServer {
  // The test payment gateway requires a callback to this server before it returns a result...
  val callbackURL = "http://" + myPublicAddress + "/callback"

  // await is from play.api.test.FutureAwaits
  val response = await(WS.url(testPaymentGatewayURL).withQueryString("callbackURL" -> callbackURL).get())

  response.status must equalTo(OK)
}

port の値には、サーバが起動しているポート番号が含まれています。デフォルトは 19001 番ですが、ポート番号を WithServer のコンストラクタに渡すか、testserver.port システムプロパティに設定することで変更することができます。これにより、ビルドごとにポート番号を動的に確保することができるので、CI サーバと統合するのに便利です。

カスタムルートを設定して WS 呼び出しをテストするのに便利な FakeApplication をテストサーバに渡すこともできます:

val appWithRoutes = FakeApplication(withRoutes = {
  case ("GET", "/") =>
    Action {
      Ok("ok")
    }
})

"test WS logic" in new WithServer(app = appWithRoutes, port = 3333) {
  await(WS.url("http://localhost:3333").get()).status must equalTo(OK)
}

§WithBrowser

ブラウザを使ってアプリケーションをテストしたい場合、Selenium WebDriver が使えます。Play は WebDriver を起動し、FluentLenium が提供する便利な API でラップします。

"run in a browser" in new WithBrowser {
  browser.goTo("/")
  browser.$("#title").getTexts().get(0) must equalTo("Hello Guest")

  browser.$("a").click()

  browser.url must equalTo("/")
  browser.$("#title").getTexts().get(0) must equalTo("Hello Coco")
}

WithServer 同様、ポート番号、 FakeApplication を変更することができますし、使用する web ブラウザを選択することもできます:

"run in a browser" in new WithBrowser(webDriver = FIREFOX) {
  ...
}

§PlaySpecification

PlaySpecification は、Play のヘルパーメソッドと一緒に使うとクラッシュする、デフォルトの specs2 スペックが提供するいくつかのミックスインを除外します。また、利便性のため Play テストヘルパと型をミックスインします。

object ExamplePlaySpecificationSpec extends PlaySpecification {
  "The specification" should {

    "have access to HeaderNames" in {
      USER_AGENT must be_===("User-Agent")
    }

    "have access to Status" in {
      OK must be_===(200)
    }
  }
}

§テンプレートのテスト

テンプレートは標準的な Scala の関数なので、テストから実行して、結果を確認することができます:

"render index template" in new WithApplication {
  val html = views.html.index("Coco")

  contentAsString(html) must contain("Hello Coco")
}

§コントローラのテスト

FakeRequest を提供することで、あらゆる Action のコードを呼び出すことができます:

object FunctionalExampleControllerSpec extends PlaySpecification {

  "respond to the index Action" in new WithApplication {
    val result = controllers.Application.index()(FakeRequest())

    status(result) must equalTo(OK)
    contentType(result) must beSome("text/plain")
    contentAsString(result) must contain("Hello Bob")
  }
}

§ルータのテスト

自分で Action を呼び出す代わりに、Router にこれを行わせることができます:

"respond to the index Action" in new WithApplication(fakeApplication) {
  val Some(result) = route(FakeRequest(GET, "/Bob"))

  status(result) must equalTo(OK)
  contentType(result) must beSome("text/html")
  charset(result) must beSome("utf-8")
  contentAsString(result) must contain("Hello Bob")
}

§モデルのテスト

SQL データベースを使っている場合、inMemoryDatabase を使ってデータベースコネクションを H2 データベースのインメモリインスタンスに置き換えることができます。

val appWithMemoryDatabase = FakeApplication(additionalConfiguration = inMemoryDatabase("test"))
"run an application" in new WithApplication(appWithMemoryDatabase) {

  val Some(macintosh) = Computer.findById(21)

  macintosh.name must equalTo("Macintosh")
  macintosh.introduced must beSome.which(_ must beEqualTo("1984-01-24"))
}

次ページ: より高度なトピック