§ScalaTest による機能テストの記述
Playには、機能テストを支援する、多くのクラスや便利なメソッドが用意されています。これらの大半は、play.api.test
パッケージか Helpers
オブジェクトに含まれています。ScalaTest + Play 統合ライブラリは、この ScalaTest のテスト支援に基づいています。
すべての Play 組み込みのテスト支援と ScalaTest + Play は、次のインポートによって利用できます。
import org.scalatest._
import play.api.test._
import play.api.test.Helpers._
import org.scalatestplus.play._
§FakeApplication
Play では頻繁に実行中の Application
をコンテキストとして実行する必要がありますが、これはたいてい play.api.Play.current
によって提供されます。
テスト用の環境を提供するために、Play は FakeApplication
クラスを提供します。このクラスは、異なる Global
オブジェクト、追加の設定、追加のプラグインによって構成されています。
val fakeApplicationWithGlobal = FakeApplication(withGlobal = Some(new GlobalSettings() {
override def onStart(app: Application) { println("Hello world!") }
}))
テストクラスの中の、すべてあるいはほとんどのテストが FakeApplication
を必要とし、すべて同一の FakeApplication
を共用可能な場合は、OneAppPerSuite
トレイトをミックスインします。app
フィールドから FakeApplication
にアクセスできます。FakeApplication
のカスタマイズが必要になったら、この例に示すように app
をオーバーライドして下さい。
class ExampleSpec extends PlaySpec with OneAppPerSuite {
// Override app if you need a FakeApplication with other than
// default parameters.
implicit override lazy val app: FakeApplication =
FakeApplication(
additionalConfiguration = Map("ehcacheplugin" -> "disabled")
)
"The OneAppPerSuite trait" must {
"provide a FakeApplication" in {
app.configuration.getString("ehcacheplugin") mustBe Some("disabled")
}
"start the FakeApplication" in {
Play.maybeApplication mustBe Some(app)
}
}
}
同一の FakeApplication
を共有するのではなく、それぞれのテストで独自の FakeApplication
を取得する必要がある場合は、代わりに OneAppPerTest
を使用します。
class ExampleSpec extends PlaySpec with OneAppPerTest {
// Override app if you need a FakeApplication with other than
// default parameters.
implicit override def newAppForTest(td: TestData): FakeApplication =
FakeApplication(
additionalConfiguration = Map("ehcacheplugin" -> "disabled")
)
"The OneAppPerTest trait" must {
"provide a new FakeApplication for each test" in {
app.configuration.getString("ehcacheplugin") mustBe Some("disabled")
}
"start the FakeApplication" in {
Play.maybeApplication mustBe Some(app)
}
}
}
ScalaTest + Play が OneAppPerSuite
と OneAppPerTest
の両方を提供する理由は、テストの実行を最も速くさせる方法を選択できるようにするためです。もし、連続したテストの中でアプリケーションの状態を維持したい場合は OneAppPerSuite
を使う必要があります。一方で、各テストでクリーンな状態が必要な場合は、OneAppPerTest
または OneAppPerSuite
のいずれかを使えますが、各テストの最後であらゆる状態をクリアしてください。さらに、テストスイートが最も速く実行され、複数のテストクラスが同一アプリケーションを共有する場合、OneAppPerSuite
をミックスインした親のスイートと、ConfiguredApp
をミックスインした入れ子のスイートを定義できます。この例については ConfiguredApp
のドキュメント で参照できます。どちらの方法でも、テストスイートを最も速く実行できるほうを使用できます。
§サーバーでのテスト
時々、実際の HTTP スタックでテストをしたい時があります。もし、テストクラスのすべてのテストが同一サーバーインスタンスを再利用可能な場合、OneServerPerSuite
をミックスインできます(スイート用の新規の FakeApplication
も提供されます)。
class ExampleSpec extends PlaySpec with OneServerPerSuite {
// Override app if you need a FakeApplication with other than
// default parameters.
implicit override lazy val app: FakeApplication =
FakeApplication(
additionalConfiguration = Map("ehcacheplugin" -> "disabled"),
withRoutes = {
case ("GET", "/") => Action { Ok("ok") }
}
)
"test server logic" in {
val myPublicAddress = s"localhost:$port"
val testPaymentGatewayURL = s"http://$myPublicAddress"
// The test payment gateway requires a callback to this server before it returns a result...
val callbackURL = s"http://$myPublicAddress/callback"
// await is from play.api.test.FutureAwaits
val response = await(WS.url(testPaymentGatewayURL).withQueryString("callbackURL" -> callbackURL).get())
response.status mustBe (OK)
}
}
もし、テストクラスのすべてのテストが独立したサーバーインスタンスを要求する場合は、代わりに OneServerPerTest
を使用します(スイート用の新規の FakeApplication
も提供されます)。
class ExampleSpec extends PlaySpec with OneServerPerTest {
// Override newAppForTest if you need a FakeApplication with other than
// default parameters.
override def newAppForTest(testData: TestData): FakeApplication =
new FakeApplication(
additionalConfiguration = Map("ehcacheplugin" -> "disabled"),
withRoutes = {
case ("GET", "/") => Action { Ok("ok") }
}
)
"The OneServerPerTest trait" must {
"test server logic" in {
val myPublicAddress = s"localhost:$port"
val testPaymentGatewayURL = s"http://$myPublicAddress"
// The test payment gateway requires a callback to this server before it returns a result...
val callbackURL = s"http://$myPublicAddress/callback"
// await is from play.api.test.FutureAwaits
val response = await(WS.url(testPaymentGatewayURL).withQueryString("callbackURL" -> callbackURL).get())
response.status mustBe (OK)
}
}
}
OneServerPerSuite
および OneServerPerTest
トレイトは、サーバーが実行しているポート番号を port
フィールドとして提供します。デフォルトは 19001 ですが、port
を上書きするか、システムプロパティ testserver.port
を設定することにより変更できます。継続的統合サーバーに組み入れる際に便利なので、各ビルドごとにポートを動的に予約できます。
前の例で示したように、app
を上書きすることで FakeApplication
をカスタマイズすることもできます。
最後に、複数のテストクラスが同一サーバーを共用できるようにすると、OneServerPerSuite
や OneServerPerTest
のアプローチよりも良いパフォーマンスが得られ、OneServerPerSuite
をミックスインするマスタースイートと ConfiguredServer
をミックインする入れ子のスイートを定義できます。ConfiguredServer
のドキュメント で例で示しています。
§Web ブラウザでのテスト
ScalaTest + Play ライブラリは ScalaTest の Selenium DSL を利用して、Web ブラウザでの Play アプリケーションのテストを簡単にします。
テストクラスのすべてのテストを同一ブラウザインスタンスを使用して実行するには、テストクラスに OneBrowserPerSuite
をミックスインします。また、ChromeFactory
、 FirefoxFactory
、 HtmlUnitFactory
、 InternetExplorerFactory
、 SafariFactory
のいずれかを Selenium Web ドライバとして提供する BrowserFactory
トレイトをミックスインする必要もあります。
BrowserFactory
のミックスインに加え、OneServerPerSuite
、
OneServerPerTest
、 ConfiguredServer
のいずれかを TestServer
として提供する ServerProvider
トレイトをミックスインする必要もあります。
例えば、以下のテストクラスは OneServerPerSuite
と HtmUnitFactory
をミックスインします。
class ExampleSpec extends PlaySpec with OneServerPerSuite with OneBrowserPerSuite with HtmlUnitFactory {
// Override app if you need a FakeApplication with other than
// default parameters.
implicit override lazy val app: FakeApplication =
FakeApplication(
additionalConfiguration = Map("ehcacheplugin" -> "disabled"),
withRoutes = {
case ("GET", "/testing") =>
Action(
Results.Ok(
"<html>" +
"<head><title>Test Page</title></head>" +
"<body>" +
"<input type='button' name='b' value='Click Me' onclick='document.title=\"scalatest\"' />" +
"</body>" +
"</html>"
).as("text/html")
)
}
)
"The OneBrowserPerTest trait" must {
"provide a web driver" in {
go to (s"http://localhost:$port/testing")
pageTitle mustBe "Test Page"
click on find(name("b")).value
eventually { pageTitle mustBe "scalatest" }
}
}
}
もし、それぞれのテストが新しいブラウザインスタンスを必要とする場合、代わりに OneBrowserPerTest
を使用します。OneBrowserPerSuite
と同様に、ServerProvider
と BrowserFactory
をミックスインする必要があります。
class ExampleSpec extends PlaySpec with OneServerPerTest with OneBrowserPerTest with HtmlUnitFactory {
// Override newAppForTest if you need a FakeApplication with other than
// default parameters.
override def newAppForTest(testData: TestData): FakeApplication =
new FakeApplication(
additionalConfiguration = Map("ehcacheplugin" -> "disabled"),
withRoutes = {
case ("GET", "/testing") =>
Action(
Results.Ok(
"<html>" +
"<head><title>Test Page</title></head>" +
"<body>" +
"<input type='button' name='b' value='Click Me' onclick='document.title=\"scalatest\"' />" +
"</body>" +
"</html>"
).as("text/html")
)
}
)
"The OneBrowserPerTest trait" must {
"provide a web driver" in {
go to (s"http://localhost:$port/testing")
pageTitle mustBe "Test Page"
click on find(name("b")).value
eventually { pageTitle mustBe "scalatest" }
}
}
}
もし、同一のブラウザインスタンスを共有する複数のテストクラスが必要な場合、OneBrowserPerSuite
を親のスイートにミックスインし、ConfiguredBrowser
を複数の入れ子スイートにミックスインします。この入れ子スイートはすべて同一の Web ブラウザを共有します。例については ConfiguredBrowser
トレイトのドキュメント を参照してください。
§複数ブラウザでの同一テストの実行
もし、アプリケーションがサポートするすべてのブラウザで正しく動作することを保証するために、テストを複数の Web ブラウザで実行したい場合は、AllBrowsersPerSuite
または AllBrowsersPerTest
トレイトを使用できます。これらのトレイトはいずれも IndexedSeq[BrowserInfo]
型の browsers
フィールドと、BrowserInfo
を引数に取る abstract メソッド sharedTests
を宣言します。browsers
フィールドはテストを実行したいブラウザを示しています。デフォルトは、Chrome、Firefox、Internet Explorer、 HtmlUnit
、Safari です。希望するブラウザとデフォルトが異なる場合は browsers
を上書きできます。複数のブラウザで実行させたいテストを sharedTests
メソッドに配置し、それぞれのテスト名の末尾にブラウザの名前を記述します。(ブラウザの名前は sharedTests
に渡される BrowserInfo
から取得できます) AllBrowsersPerSuite
を使用した例はこちらです。
class ExampleSpec extends PlaySpec with OneServerPerSuite with AllBrowsersPerSuite {
// Override app if you need a FakeApplication with other than
// default parameters.
implicit override lazy val app: FakeApplication =
FakeApplication(
additionalConfiguration = Map("ehcacheplugin" -> "disabled"),
withRoutes = {
case ("GET", "/testing") =>
Action(
Results.Ok(
"<html>" +
"<head><title>Test Page</title></head>" +
"<body>" +
"<input type='button' name='b' value='Click Me' onclick='document.title=\"scalatest\"' />" +
"</body>" +
"</html>"
).as("text/html")
)
}
)
def sharedTests(browser: BrowserInfo) = {
"The AllBrowsersPerSuite trait" must {
"provide a web driver " + browser.name in {
go to (s"http://localhost:$port/testing")
pageTitle mustBe "Test Page"
click on find(name("b")).value
eventually { pageTitle mustBe "scalatest" }
}
}
}
}
sharedTests
によって宣言されたすべてのテストは、browsers
フィールドで定義されているすべてのブラウザで、それらがホストシステムで利用できれば、実行されます。ホストシステムで利用できない、いずれのブラウザのテストも自動的にキャンセルされます。スイートの各テストが (ScalaTest によって要求された) 一意的な名前を持つように、テスト名に browser.name
を手動で追加する必要があることに注意して下さい。もしこれを行わなかった場合、テストの実行時にテスト名の重複エラーが発生します。
AllBrowsersPerSuite
はブラウザのタイプごとに 1 つのインスタンスを生成し、sharedTests
で宣言したすべてのテストに対して使用します。もし、各テストで独自の新しいブラウザインスタンスが必要な場合は、代わりに AllBrowsersPerTest
を使用してくだい。
class ExampleSpec extends PlaySpec with OneServerPerSuite with AllBrowsersPerTest {
// Override app if you need a FakeApplication with other than
// default parameters.
implicit override lazy val app: FakeApplication =
FakeApplication(
additionalConfiguration = Map("ehcacheplugin" -> "disabled"),
withRoutes = {
case ("GET", "/testing") =>
Action(
Results.Ok(
"<html>" +
"<head><title>Test Page</title></head>" +
"<body>" +
"<input type='button' name='b' value='Click Me' onclick='document.title=\"scalatest\"' />" +
"</body>" +
"</html>"
).as("text/html")
)
}
)
def sharedTests(browser: BrowserInfo) = {
"The AllBrowsersPerTest trait" must {
"provide a web driver" + browser.name in {
go to (s"http://localhost:$port/testing")
pageTitle mustBe "Test Page"
click on find(name("b")).value
eventually { pageTitle mustBe "scalatest" }
}
}
}
}
AllBrowsersPerSuite
と AllBrowsersPerTest
は共に、利用できないブラウザタイプのテストはキャンセルしますが、テストがキャンセルされたこと自体は出力で明示されます。出力を綺麗にするために、次の例のように browsers
を上書きすることにより、利用できない Web ブラウザを除外できます。
class ExampleOverrideBrowsersSpec extends PlaySpec with OneServerPerSuite with AllBrowsersPerSuite {
override lazy val browsers =
Vector(
FirefoxInfo(firefoxProfile),
ChromeInfo
)
// Override app if you need a FakeApplication with other than
// default parameters.
implicit override lazy val app: FakeApplication =
FakeApplication(
additionalConfiguration = Map("ehcacheplugin" -> "disabled"),
withRoutes = {
case ("GET", "/testing") =>
Action(
Results.Ok(
"<html>" +
"<head><title>Test Page</title></head>" +
"<body>" +
"<input type='button' name='b' value='Click Me' onclick='document.title=\"scalatest\"' />" +
"</body>" +
"</html>"
).as("text/html")
)
}
)
def sharedTests(browser: BrowserInfo) = {
"The AllBrowsersPerSuite trait" must {
"provide a web driver" + browser.name in {
go to (s"http://localhost:$port/testing")
pageTitle mustBe "Test Page"
click on find(name("b")).value
eventually { pageTitle mustBe "scalatest" }
}
}
}
}
前述のテストクラスは、Firefox と Chrome でのみ、共有されたテストの実行を試みます (そしてブラウザが利用できない場合は自動的にテストはキャンセルされます)。
§PlaySpec
PlaySpec
は Play のテストでの便利な「スーパースイート」 ScalaTest ベースクラスを提供し、PlaySpec
の継承によって、 WordSpec
、 MustMatchers
、 OptionValues
、 WsScalaTestClient
を自動的に利用できます。
class ExampleSpec extends PlaySpec with OneServerPerSuite with ScalaFutures with IntegrationPatience {
// Override app if you need a FakeApplication with other than
// default parameters.
implicit override lazy val app: FakeApplication =
FakeApplication(
additionalConfiguration = Map("ehcacheplugin" -> "disabled"),
withRoutes = {
case ("GET", "/testing") =>
Action(
Results.Ok(
"<html>" +
"<head><title>Test Page</title></head>" +
"<body>" +
"<input type='button' name='b' value='Click Me' onclick='document.title=\"scalatest\"' />" +
"</body>" +
"</html>"
).as("text/html")
)
}
)
"WsScalaTestClient's" must {
"wsUrl works correctly" in {
val futureResult = wsUrl("/testing").get
val body = futureResult.futureValue.body
val expectedBody =
"<html>" +
"<head><title>Test Page</title></head>" +
"<body>" +
"<input type='button' name='b' value='Click Me' onclick='document.title=\"scalatest\"' />" +
"</body>" +
"</html>"
assert(body == expectedBody)
}
"wsCall works correctly" in {
val futureResult = wsCall(Call("get", "/testing")).get
val body = futureResult.futureValue.body
val expectedBody =
"<html>" +
"<head><title>Test Page</title></head>" +
"<body>" +
"<input type='button' name='b' value='Click Me' onclick='document.title=\"scalatest\"' />" +
"</body>" +
"</html>"
assert(body == expectedBody)
}
}
}
前述のいずれのトレイトも PlaySpec
にミックスインできます。
§異なるテストが異なるフィクスチャーを必要とする場合
前述の例で示したすべてのテストクラスにおいて、テストクラスの中のすべてもしくはほとんどのテストは同一のフィクスチャーを必要とします。これは一般的ですが、必ずしもそうではありません。同一テストクラスの中の異なるテストが異なるフィクスチャーを必要とする場合、MixedFixtures
トレイトをミックスインします。そして、次のような引数なし関数のいずれかを使用して、必要なフィクスチャーを個々のテストに与えます。 App 、 Server 、 Chrome 、 Firefox 、 HtmlUnit 、 InternetExplorer 、 Safari 。
MixedFixtures
は ScalaTest の fixture.Suite
を必要とし、PlaySpec
は単なる標準の Suite
であるため、MixedFixtures
を PlaySpec
にミックスインできません。ミックスインされたフィクスチャー向けの便利なベースクラスが欲しい場合は、代わりに MixedPlaySpec
を継承します。例はこちらです。
// MixedPlaySpec already mixes in MixedFixtures
class ExampleSpec extends MixedPlaySpec {
// Some helper methods
def fakeApp[A](elems: (String, String)*) = FakeApplication(additionalConfiguration = Map(elems:_*),
withRoutes = {
case ("GET", "/testing") =>
Action(
Results.Ok(
"<html>" +
"<head><title>Test Page</title></head>" +
"<body>" +
"<input type='button' name='b' value='Click Me' onclick='document.title=\"scalatest\"' />" +
"</body>" +
"</html>"
).as("text/html")
)
})
def getConfig(key: String)(implicit app: Application) = app.configuration.getString(key)
// If a test just needs a FakeApplication, use "new App":
"The App function" must {
"provide a FakeApplication" in new App(fakeApp("ehcacheplugin" -> "disabled")) {
app.configuration.getString("ehcacheplugin") mustBe Some("disabled")
}
"make the FakeApplication available implicitly" in new App(fakeApp("ehcacheplugin" -> "disabled")) {
getConfig("ehcacheplugin") mustBe Some("disabled")
}
"start the FakeApplication" in new App(fakeApp("ehcacheplugin" -> "disabled")) {
Play.maybeApplication mustBe Some(app)
}
}
// If a test needs a FakeApplication and running TestServer, use "new Server":
"The Server function" must {
"provide a FakeApplication" in new Server(fakeApp("ehcacheplugin" -> "disabled")) {
app.configuration.getString("ehcacheplugin") mustBe Some("disabled")
}
"make the FakeApplication available implicitly" in new Server(fakeApp("ehcacheplugin" -> "disabled")) {
getConfig("ehcacheplugin") mustBe Some("disabled")
}
"start the FakeApplication" in new Server(fakeApp("ehcacheplugin" -> "disabled")) {
Play.maybeApplication mustBe Some(app)
}
import Helpers._
"send 404 on a bad request" in new Server {
import java.net._
val url = new URL("http://localhost:" + port + "/boom")
val con = url.openConnection().asInstanceOf[HttpURLConnection]
try con.getResponseCode mustBe 404
finally con.disconnect()
}
}
// If a test needs a FakeApplication, running TestServer, and Selenium
// HtmlUnit driver use "new HtmlUnit":
"The HtmlUnit function" must {
"provide a FakeApplication" in new HtmlUnit(fakeApp("ehcacheplugin" -> "disabled")) {
app.configuration.getString("ehcacheplugin") mustBe Some("disabled")
}
"make the FakeApplication available implicitly" in new HtmlUnit(fakeApp("ehcacheplugin" -> "disabled")) {
getConfig("ehcacheplugin") mustBe Some("disabled")
}
"start the FakeApplication" in new HtmlUnit(fakeApp("ehcacheplugin" -> "disabled")) {
Play.maybeApplication mustBe Some(app)
}
import Helpers._
"send 404 on a bad request" in new HtmlUnit {
import java.net._
val url = new URL("http://localhost:" + port + "/boom")
val con = url.openConnection().asInstanceOf[HttpURLConnection]
try con.getResponseCode mustBe 404
finally con.disconnect()
}
"provide a web driver" in new HtmlUnit(fakeApp()) {
go to ("http://localhost:" + port + "/testing")
pageTitle mustBe "Test Page"
click on find(name("b")).value
eventually { pageTitle mustBe "scalatest" }
}
}
// If a test needs a FakeApplication, running TestServer, and Selenium
// Firefox driver use "new Firefox":
"The Firefox function" must {
"provide a FakeApplication" in new Firefox(fakeApp("ehcacheplugin" -> "disabled")) {
app.configuration.getString("ehcacheplugin") mustBe Some("disabled")
}
"make the FakeApplication available implicitly" in new Firefox(fakeApp("ehcacheplugin" -> "disabled")) {
getConfig("ehcacheplugin") mustBe Some("disabled")
}
"start the FakeApplication" in new Firefox(fakeApp("ehcacheplugin" -> "disabled")) {
Play.maybeApplication mustBe Some(app)
}
import Helpers._
"send 404 on a bad request" in new Firefox {
import java.net._
val url = new URL("http://localhost:" + port + "/boom")
val con = url.openConnection().asInstanceOf[HttpURLConnection]
try con.getResponseCode mustBe 404
finally con.disconnect()
}
"provide a web driver" in new Firefox(fakeApp()) {
go to ("http://localhost:" + port + "/testing")
pageTitle mustBe "Test Page"
click on find(name("b")).value
eventually { pageTitle mustBe "scalatest" }
}
}
// If a test needs a FakeApplication, running TestServer, and Selenium
// Safari driver use "new Safari":
"The Safari function" must {
"provide a FakeApplication" in new Safari(fakeApp("ehcacheplugin" -> "disabled")) {
app.configuration.getString("ehcacheplugin") mustBe Some("disabled")
}
"make the FakeApplication available implicitly" in new Safari(fakeApp("ehcacheplugin" -> "disabled")) {
getConfig("ehcacheplugin") mustBe Some("disabled")
}
"start the FakeApplication" in new Safari(fakeApp("ehcacheplugin" -> "disabled")) {
Play.maybeApplication mustBe Some(app)
}
import Helpers._
"send 404 on a bad request" in new Safari {
import java.net._
val url = new URL("http://localhost:" + port + "/boom")
val con = url.openConnection().asInstanceOf[HttpURLConnection]
try con.getResponseCode mustBe 404
finally con.disconnect()
}
"provide a web driver" in new Safari(fakeApp()) {
go to ("http://localhost:" + port + "/testing")
pageTitle mustBe "Test Page"
click on find(name("b")).value
eventually { pageTitle mustBe "scalatest" }
}
}
// If a test needs a FakeApplication, running TestServer, and Selenium
// Chrome driver use "new Chrome":
"The Chrome function" must {
"provide a FakeApplication" in new Chrome(fakeApp("ehcacheplugin" -> "disabled")) {
app.configuration.getString("ehcacheplugin") mustBe Some("disabled")
}
"make the FakeApplication available implicitly" in new Chrome(fakeApp("ehcacheplugin" -> "disabled")) {
getConfig("ehcacheplugin") mustBe Some("disabled")
}
"start the FakeApplication" in new Chrome(fakeApp("ehcacheplugin" -> "disabled")) {
Play.maybeApplication mustBe Some(app)
}
import Helpers._
"send 404 on a bad request" in new Chrome {
import java.net._
val url = new URL("http://localhost:" + port + "/boom")
val con = url.openConnection().asInstanceOf[HttpURLConnection]
try con.getResponseCode mustBe 404
finally con.disconnect()
}
"provide a web driver" in new Chrome(fakeApp()) {
go to ("http://localhost:" + port + "/testing")
pageTitle mustBe "Test Page"
click on find(name("b")).value
eventually { pageTitle mustBe "scalatest" }
}
}
// If a test needs a FakeApplication, running TestServer, and Selenium
// InternetExplorer driver use "new InternetExplorer":
"The InternetExplorer function" must {
"provide a FakeApplication" in new InternetExplorer(fakeApp("ehcacheplugin" -> "disabled")) {
app.configuration.getString("ehcacheplugin") mustBe Some("disabled")
}
"make the FakeApplication available implicitly" in new InternetExplorer(fakeApp("ehcacheplugin" -> "disabled")) {
getConfig("ehcacheplugin") mustBe Some("disabled")
}
"start the FakeApplication" in new InternetExplorer(fakeApp("ehcacheplugin" -> "disabled")) {
Play.maybeApplication mustBe Some(app)
}
import Helpers._
"send 404 on a bad request" in new InternetExplorer {
import java.net._
val url = new URL("http://localhost:" + port + "/boom")
val con = url.openConnection().asInstanceOf[HttpURLConnection]
try con.getResponseCode mustBe 404
finally con.disconnect()
}
"provide a web driver" in new InternetExplorer(fakeApp()) {
go to ("http://localhost:" + port + "/testing")
pageTitle mustBe "Test Page"
click on find(name("b")).value
eventually { pageTitle mustBe "scalatest" }
}
}
// If a test does not need any special fixtures, just
// write "in { () => ..."
"Any old thing" must {
"be doable without much boilerplate" in { () =>
1 + 1 mustEqual 2
}
}
}
§テンプレートのテスト
テンプレートは標準的な Scala の機能なので、テストから実行でき、そして結果を確認できます。
"render index template" in new App {
val html = views.html.index("Coco")
contentAsString(html) must include ("Hello Coco")
}
§コントローラーのテスト
FakeRequest
の提供による、いずれの Action
コードも呼び出すことができます。
import scala.concurrent.Future
import org.scalatest._
import org.scalatestplus.play._
import play.api.mvc._
import play.api.test._
import play.api.test.Helpers._
class ExampleControllerSpec extends PlaySpec with Results {
class TestController() extends Controller with ExampleController
"Example Page#index" should {
"should be valid" in {
val controller = new TestController()
val result: Future[Result] = controller.index().apply(FakeRequest())
val bodyText: String = contentAsString(result)
bodyText mustBe "ok"
}
}
}
技術的に、ここで WithApplication
は不要ですが、それにより何かを損なうことはありません。
§ルーターのテスト
自分で Action
を呼び出す代わりに、Router
にそれをさせることができます。
"respond to the index Action" in new App(fakeApplication) {
val Some(result) = route(FakeRequest(GET, "/Bob"))
status(result) mustEqual OK
contentType(result) mustEqual Some("text/html")
charset(result) mustEqual Some("utf-8")
contentAsString(result) must include ("Hello Bob")
}
§モデルのテスト
SQL データベースを使用する時、inMemoryDatabase
を使用して H2 データベースのインメモリインスタンスでデータベース接続を置き換えることができます。
val appWithMemoryDatabase = FakeApplication(additionalConfiguration = inMemoryDatabase("test"))
"run an application" in new App(appWithMemoryDatabase) {
val Some(macintosh) = Computer.findById(21)
macintosh.name mustEqual "Macintosh"
macintosh.introduced.value mustEqual "1984-01-24"
}
§WS 呼び出しのテスト
Web サービスの呼び出しを行う時、WSTestClient
を使用することができます。wsCall
と wsUrl
の 2 つの呼び出しが可能で、それぞれ Call または文字列を引数に取ります。WithApplication
のコンテキスト内での呼び出しが期待されていることに注意してください。
wsCall(controllers.routes.Application.index()).get()
wsUrl("http://localhost:9000").get()
Next: Specs2 によるテスト
このドキュメントの翻訳は Play チームによってメンテナンスされているものではありません。 間違いを見つけた場合、このページのソースコードを ここ で確認することができます。 ドキュメントガイドライン を読んで、お気軽にプルリクエストを送ってください。