PlayFrameworkでのcontrollerのテストのやり方メモ - $shibayu36->blog; でPlay FrameworkにおけるControllerの基本的なテスト方法について学んだ。ただ、テスト用のApplicationを作るためのtraitにGuiceOneAppPerSuiteとGuiceOneAppPerTestというのがあって、どういう違いか分からなかったので調べた。
コード上のコメントが一番参考になった。
- GuiceOneAppPerSuite: https://github.com/playframework/scalatestplus-play/blob/master/module/src/main/scala/org/scalatestplus/play/guice/GuiceOneAppPerSuite.scala
- GuiceOneAppPerTest: https://github.com/playframework/scalatestplus-play/blob/master/module/src/main/scala/org/scalatestplus/play/guice/GuiceOneAppPerTest.scala
これによると、GuiceOneAppPerSuiteはSpec全体で一つのApplicationを共有していて、GuiceOneAppPerTestはすべてのテスト(FunSpecにおけるitの単位?)でApplicationを作るようになっているっぽい?
というわけで動かしてみて試した。
GuiceOneAppPerSuite
https://github.com/playframework/play-scala-seed.g8/blob/2.6.x/src/main/g8/app/controllers/HomeController.scala のcontrollerに対して、以下のコードを動かしてみる。
package controllers import org.scalatest.{TestData, FunSpec} import play.api.test._ import play.api.test.Helpers._ import play.api.inject.guice._ import play.api.Application import org.scalatestplus.play.guice.{GuiceOneAppPerTest, GuiceOneAppPerSuite} class HomeControllerSpec extends FunSpec with GuiceOneAppPerSuite with org.scalatest.Matchers { override def fakeApplication(): Application = { println("fuga") new GuiceApplicationBuilder().configure(Map("ehcacheplugin" -> "disabled")).build() } for (i <- 1 to 5) { describe("HomeController GET" + i) { it("render the index page from a new instance of controller" + i) { val controller = new HomeController(stubControllerComponents()) val home = controller.index().apply(FakeRequest(GET, "/")) status(home) shouldBe OK contentType(home) shouldBe Some("text/html") contentAsString(home) should include ("Welcome to Play") } it("render the index page from a new instance of controller" + i * 10) { val controller = new HomeController(stubControllerComponents()) val home = controller.index().apply(FakeRequest(GET, "/")) status(home) shouldBe OK contentType(home) shouldBe Some("text/html") contentAsString(home) should include ("Welcome to Play") } } } }
これでテストを実行すると、fugaは一回しか出力されず、ただ一度だけApplicationが作られていそう。
$ testOnly controllers.HomeControllerSpec [info] HomeControllerSpec: fuga [info] HomeController GET1 [info] - render the index page from a new instance of controller1 [info] - render the index page from a new instance of controller10 [info] HomeController GET2 [info] - render the index page from a new instance of controller2 [info] - render the index page from a new instance of controller20 [info] HomeController GET3 [info] - render the index page from a new instance of controller3 [info] - render the index page from a new instance of controller30 [info] HomeController GET4 [info] - render the index page from a new instance of controller4 [info] - render the index page from a new instance of controller40 [info] HomeController GET5 [info] - render the index page from a new instance of controller5 [info] - render the index page from a new instance of controller50 [info] ScalaTest [info] Run completed in 4 seconds, 137 milliseconds. [info] Total number of tests run: 10 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 10, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed. [info] Passed: Total 10, Failed 0, Errors 0, Passed 10 [success] Total time: 5 s, completed Sep 1, 2017 8:00:19 AM
GuiceOneAppPerTest
続いて、GuiceOneAppPerTestを使ってみる。
package controllers import org.scalatest.{TestData, FunSpec} import play.api.test._ import play.api.test.Helpers._ import play.api.inject.guice._ import play.api.Application import org.scalatestplus.play.guice.{GuiceOneAppPerTest, GuiceOneAppPerSuite} class HomeControllerSpec extends FunSpec with GuiceOneAppPerTest with org.scalatest.Matchers { override def newAppForTest(td: TestData) = { println("hoge") new GuiceApplicationBuilder().configure(Map("ehcacheplugin" -> "disabled")).build() } for (i <- 1 to 5) { describe("HomeController GET" + i) { it("render the index page from a new instance of controller" + i) { val controller = new HomeController(stubControllerComponents()) val home = controller.index().apply(FakeRequest(GET, "/")) status(home) shouldBe OK contentType(home) shouldBe Some("text/html") contentAsString(home) should include ("Welcome to Play") } it("render the index page from a new instance of controller" + i * 10) { val controller = new HomeController(stubControllerComponents()) val home = controller.index().apply(FakeRequest(GET, "/")) status(home) shouldBe OK contentType(home) shouldBe Some("text/html") contentAsString(home) should include ("Welcome to Play") } } } }
これも実行してみると以下のようになり、hogeがitの単位でprintされているので、itの単位でApplicationが作り直されていそう。
$ testOnly controllers.HomeControllerSpec [info] Compiling 1 Scala source to /Users/shibayu36/development/src/github.com/shibayu36/scala-play-blog/target/scala-2.12/test-classes... [info] HomeControllerSpec: [info] HomeController GET1 hoge [info] - render the index page from a new instance of controller1 hoge [info] - render the index page from a new instance of controller10 [info] HomeController GET2 hoge [info] - render the index page from a new instance of controller2 hoge [info] - render the index page from a new instance of controller20 [info] HomeController GET3 hoge [info] - render the index page from a new instance of controller3 hoge [info] - render the index page from a new instance of controller30 [info] HomeController GET4 hoge [info] - render the index page from a new instance of controller4 hoge [info] - render the index page from a new instance of controller40 [info] HomeController GET5 hoge [info] - render the index page from a new instance of controller5 hoge [info] - render the index page from a new instance of controller50 [info] ScalaTest [info] Run completed in 4 seconds, 925 milliseconds. [info] Total number of tests run: 10 [info] Suites: completed 1, aborted 0 [info] Tests: succeeded 10, failed 0, canceled 0, ignored 0, pending 0 [info] All tests passed. [info] Passed: Total 10, Failed 0, Errors 0, Passed 10 [success] Total time: 6 s, completed Sep 1, 2017 8:01:54 AM
まとめ
今回はテスト用のApplicationを作るためのtraitにGuiceOneAppPerSuiteとGuiceOneAppPerTestの違いについて、テストコードを動かしながら確認してみた。まだScala & PlayFramework初心者なのでもしかしたら間違ってるかもしれない。間違っていたら教えてください。
参考
- PlayFrameworkでのcontrollerのテストのやり方メモ - $shibayu36->blog;
- GuiceOneAppPerSuite: https://github.com/playframework/scalatestplus-play/blob/master/module/src/main/scala/org/scalatestplus/play/guice/GuiceOneAppPerSuite.scala
- GuiceOneAppPerTest: https://github.com/playframework/scalatestplus-play/blob/master/module/src/main/scala/org/scalatestplus/play/guice/GuiceOneAppPerTest.scala
- https://github.com/playframework/play-scala-seed.g8/blob/2.6.x/src/main/g8/app/controllers/HomeController.scala