Search code examples
scalaspecs2

Specs2 Steps not executing in order


I am attempting to execute a Specification with multiple tests that all run within the same Play application and not a separate application for each test.

As such I have the following code which should print:

Play app started
[info] PlayRunningImmutableSpec
[info]     
[info]     + 200 status expected
[info]     
[info]     + 404 status expected
Play app stopped

but instead prints:

Play app started
Play app stopped
[info] PlayRunningImmutableSpec
[info]     
[info] 
[info]     ! 200 status expected
[error]  ConnectException: : Connection refused: /127.0.0.1:19001 to http://127.0.0.1:19001/

I am using Typesafe Activator 1.2.10 which includes Play 2.3.3 and Specs2 2.3.12

What is wrong with the following code, and what would work instead?

import org.specs2.Specification
import org.specs2.execute.Result
import org.specs2.specification.Step
import org.specs2.time.NoTimeConversions
import play.api.Play
import play.api.Play.current
import play.api.http.{HeaderNames, HttpProtocol, Status}
import play.api.libs.ws.WS
import play.api.test._

class PlayRunningImmutableSpec extends Specification with NoTimeConversions with PlayRunners with HeaderNames with Status with HttpProtocol with DefaultAwaitTimeout with ResultExtractors with Writeables with RouteInvokers with FutureAwaits {

  override def is = s2"""
    ${Step(beforeAll)}

    200 status expected      $e1

    404 status expected      $e2

    ${Step(afterAll)}
  """

  def e1: Result = {
    await(WS.url(s"http://127.0.0.1:${Helpers.testServerPort}").get()).status === 200
  }

  def e2: Result = {
    await(WS.url(s"http://127.0.0.1:${Helpers.testServerPort}/missing").get()).status === 404
  }

  lazy val app = FakeApplication()

  private def beforeAll = {
    Play.start(app)
    println("Play app started")
  }

  private def afterAll = {
    Play.stop()
    println("Play app stopped")
  }
}

EDIT:

I realised my error was in the use the play.api.Play.start method and now have a simple trait to handle one startup and shutdown:

trait PlayServerRunning extends SpecificationLike {

  override def map(fs: => Fragments): Fragments = Step(beforeAll) ^ fs ^ Step(afterAll)

  private lazy val server = TestServer(Helpers.testServerPort)

  private def beforeAll = {
    server.start()
  }

  private def afterAll = {
    server.stop()
  }

}

Solution

  • That's on propose. Tests are executed in parallel (with implementation details according execution context).

    If your tests need to be sequential, you must annotate in this way. e.g.:

    "X" should {
      sequential
    
      "exp1" in { ... }
      "exp2" in { ... }
    }