Fast test execution in a playframework fake application

playframework, playframework-2.2, scala, specs2

Solution

I don't know if it is the best possible solution but in this thread: Execute code before and after specification

You can read a solution for reusable code. I implemented it with little modifications. For me the beforeAll step did not run and added the `sequential` modifier.

import org.specs2.mutable._
import org.specs2.specification._

class PlayAppSpec extends Specification with BeforeAllAfterAll{
    sequential
    lazy val app : FakeApplication = {
        FakeApplication()
    }

    def beforeAll(){
        Play.start(app)
    }

    def afterAll(){
        Play.stop()
    }
}
import org.specs2.specification.Step

trait BeforeAllAfterAll extends Specification {
  // see specs2 User Guide, linked below
  override def map(fragments: =>Fragments) = {
    beforeAll()
    fragments ^ Step(afterAll)
  }
    

  def beforeAll()
  def afterAll()
}

I think the `map` would be better with `Step(...) ^ fragments ^ Step(...)` but it did not run the beforeAll for me. The user guide at "Global setup/teardown" says to use a lazy val.

Overall it was a pain to set up this. My problem was `Exception in thread "Thread-145" java.net.SocketException: Connection reset` Or

`Configuration error[Cannot connect to database [default]] (Configuration.scala:559)`

When reusing the same FakeApplication: `SQLException: Attempting to obtain a connection from a pool that has already been shutdown. `

I think it is much more logical this way than always creating a new application for every "in" block or adding all tests into one block.

Problem

Running tests as described here ``` "Spec" should { "example" in new WithApplication { ... } } ``` is unacceptably slow for me. This is because new WithApplication is starting and stoping framework at every example. Don't get me wrong, a framework itself loads very fast, but if database is configured (surprise!), situation becomes terrible. Here are some measurments: ``` "The database layer" should { "test1" in { 1 must be equalTo(1) } ... "test20" in { 1 must be equalTo(1) } } ``` Execution time: 2 seconds. Same test with WithApplication at every example consumes 9 seconds I was able to achive much better results thanks to this answer ``` import play.api.Play import play.api.test.FakeApplication import org.specs2.mutable.Specification import scalikejdbc._ class MySpec extends Specification { var fake: FakeApplication = _ step {fake = FakeApplication(...)} step {Play.start(fake)} "The database layer" should { "some db test" in { DB localTx { implicit session => ... } } "another db test" in { DB localTx { implicit session => ... } } step {Play.stop()} } ``` } Pros: performance boost Cons: need to copy-paste setup and tear-down code because don't know how to reuse it (by reuse I mean something like "class MySpec extends Specification with NoWasteOfTime" new WithApplication() calls Helpers.running which looks like this ``` synchronized { try { Play.start(fakeApp) block } finally { Play.stop() play.api.libs.ws.WS.resetClient() } } ``` so I can't completely emulate Helpers.running behaviour (resetClient is not visible for my code) without reflection. Please suggest how to break cons or different approach how accomplish my issue.

Original source