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.