§機能テストを書く
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
が提供されています。
WithApplication
は Around
ブロックに組み込まれているので、自身のデータで上書きすることができます。
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"))
}
次ページ: より高度なトピック