Skip to content

Commit

Permalink
playframework#112 - don't extend sync line of suites
Browse files Browse the repository at this point in the history
this allows implementing specs to use either sync or async suites
  • Loading branch information
kwinter committed Apr 25, 2020
1 parent cc39d1e commit ce6a5f9
Show file tree
Hide file tree
Showing 21 changed files with 102 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ package org.scalatestplus.play

import org.scalatest.Args
import org.scalatest.Status
import org.scalatest.TestSuite
import org.scalatest.TestSuiteMixin
import org.scalatest.Suite
import org.scalatest.SuiteMixin
import play.api.Application
import play.api.Play

/**
* The base abstract trait for one app per suite.
*/
trait BaseOneAppPerSuite extends TestSuiteMixin { this: TestSuite with FakeApplicationFactory =>
trait BaseOneAppPerSuite extends SuiteMixin { this: Suite with FakeApplicationFactory =>

/**
* An implicit instance of `Application`.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package org.scalatestplus.play

import org.scalatest.BeforeAndAfterEachTestData
import org.scalatest.TestData
import org.scalatest.TestSuite
import org.scalatest.TestSuiteMixin
import org.scalatest.Suite
import org.scalatest.SuiteMixin
import play.api.Application
import play.api.Play
import play.api.test.Helpers

/**
* Trait that provides a new `Application` instance for each test.
*
* This `TestSuiteMixin` trait's overridden `withFixture` method creates a new `Application`
* This `SuiteMixin` trait's overridden `withFixture` method creates a new `Application`
* before each test and ensures it is cleaned up after the test has completed. You can
* access the `Application` from your tests as method `app` (which is marked implicit).
*
Expand Down Expand Up @@ -45,7 +47,8 @@ import play.api.test.Helpers
* }
* </pre>
*/
trait BaseOneAppPerTest extends TestSuiteMixin with AppProvider { this: TestSuite with FakeApplicationFactory =>
trait BaseOneAppPerTest extends SuiteMixin with BeforeAndAfterEachTestData with AppProvider {
this: Suite with FakeApplicationFactory =>

/**
* Creates new instance of `Application` with parameters set to their defaults. Override this method if you
Expand All @@ -60,18 +63,18 @@ trait BaseOneAppPerTest extends TestSuiteMixin with AppProvider { this: TestSuit
*/
final implicit def app: Application = synchronized { appPerTest }

/**
* Creates a new `Application` instance before executing each test, and
* ensure it is cleaned up after the test completes. You can access the `Application` from
* your tests via `app`.
*
* @param test the no-arg test function to run with a fixture
* @return the `Outcome` of the test execution
*/
abstract override def withFixture(test: NoArgTest) = {
synchronized { appPerTest = newAppForTest(test) }
Helpers.running(app) {
super.withFixture(test)
override def beforeEach(td: TestData): Unit = {
synchronized { appPerTest = newAppForTest(td) }
Play.start(appPerTest)
super.beforeEach(td)
}

override def afterEach(td: TestData): Unit = {
try {
super.afterEach(td)
} finally {
Play.stop(appPerTest)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import play.api.test._
* `Application` with non-default parameters, override `app`. If it needs a different port number,
* override `port`.
*
* This `TestSuiteMixin` trait's overridden `run` method calls `start` on the `TestServer`
* This `SuiteMixin` trait's overridden `run` method calls `start` on the `TestServer`
* before executing the `Suite` via a call to `super.run`.
* In addition, it places a reference to the `Application` provided by `app` into the `ConfigMap`
* under the key `org.scalatestplus.play.app` and to the port number provided by `port` under the key
Expand Down Expand Up @@ -134,7 +134,7 @@ import play.api.test._
* }
* </pre>
*/
trait BaseOneServerPerSuite extends TestSuiteMixin with ServerProvider { this: TestSuite with FakeApplicationFactory =>
trait BaseOneServerPerSuite extends SuiteMixin with ServerProvider { this: Suite with FakeApplicationFactory =>

/**
* An implicit instance of `Application`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import org.scalatest._
/**
* Trait that provides a new `Application` and running `TestServer` instance for each test executed in a ScalaTest `Suite`.
*
* This `TestSuiteMixin` trait overrides ScalaTest's `withFixture` method to create a new `Application` and `TestServer`
* This `SuiteMixin` trait overrides ScalaTest's `withFixture` method to create a new `Application` and `TestServer`
* before each test, and ensure they are cleaned up after the test has completed. The `Application` is available (implicitly) from
* method `app`. The `TestServer`'s port number is available as `port` (and implicitly available as `portNumber`, wrapped
* in a [[org.scalatestplus.play.PortNumber PortNumber]]).
Expand Down Expand Up @@ -73,7 +73,8 @@ import org.scalatest._
* }
* </pre>
*/
trait BaseOneServerPerTest extends TestSuiteMixin with ServerProvider { this: TestSuite with FakeApplicationFactory =>
trait BaseOneServerPerTest extends SuiteMixin with BeforeAndAfterEachTestData with ServerProvider {
this: Suite with FakeApplicationFactory =>

@volatile private var privateApp: Application = _
@volatile private var privateServer: RunningServer = _
Expand Down Expand Up @@ -108,28 +109,23 @@ trait BaseOneServerPerTest extends TestSuiteMixin with ServerProvider { this: Te
protected def newServerForTest(app: Application, testData: TestData): RunningServer =
DefaultTestServerFactory.start(app)

/**
* Creates new `Application` and running `TestServer` instances before executing each test, and
* ensures they are cleaned up after the test completes. You can access the `Application` from
* your tests as `app` and the `TestServer`'s port number as `port`.
*
* @param test the no-arg test function to run with a fixture
* @return the `Outcome` of the test execution
*/
abstract override def withFixture(test: NoArgTest) = {
// Need to synchronize within a suite because we store current app/server in fields in the class
// Could possibly pass app/server info in a ScalaTest object?
override def beforeEach(td: TestData): Unit = {
lock.synchronized {
privateApp = newAppForTest(test)
privateServer = newServerForTest(app, test)
try super.withFixture(test)
finally {
val rs = privateServer // Store before nulling fields
privateApp = null
privateServer = null
// Stop server and release locks
rs.stopServer.close()
}
privateApp = newAppForTest(td)
privateServer = newServerForTest(app, td)
}
super.beforeEach(td)
}

override def afterEach(td: TestData): Unit = {
try {
super.afterEach(td)
} finally {
val rs = privateServer // Store before nulling fields
privateApp = null
privateServer = null
// Stop server and release locks
rs.stopServer.close()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import play.api.Application
* }
* </pre>
*/
trait ConfiguredApp extends TestSuiteMixin { this: TestSuite =>
trait ConfiguredApp extends SuiteMixin { this: Suite =>

private var configuredApp: Application = _

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ import org.scalatestplus.selenium.WebBrowser
* }
* </pre>
*/
trait ConfiguredBrowser extends TestSuiteMixin with WebBrowser with Eventually with IntegrationPatience {
this: TestSuite with ServerProvider =>
trait ConfiguredBrowser extends SuiteMixin with WebBrowser with Eventually with IntegrationPatience {
this: Suite with ServerProvider =>

private var configuredWebDriver: WebDriver = UninitializedDriver

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ import play.core.server.ServerEndpoints
* }
* </pre>
*/
trait ConfiguredServer extends TestSuiteMixin with ServerProvider { this: TestSuite =>
trait ConfiguredServer extends SuiteMixin with ServerProvider { this: Suite =>

private var configuredApp: Application = _

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ import org.scalatestplus.play.guice.GuiceOneAppPerSuite
* Synonym for GuiceOneAppPerSuite.
*/
@deprecated("Use GuiceOneAppPerSuite instead", "2.0.0")
trait OneAppPerSuite extends GuiceOneAppPerSuite { this: TestSuite =>
trait OneAppPerSuite extends GuiceOneAppPerSuite { this: Suite =>

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ import org.scalatestplus.play.guice.GuiceOneAppPerTest
* Synonym for GuiceOneAppPerTest
*/
@deprecated("Use GuiceOneAppPerTest instead", "2.0.0")
trait OneAppPerTest extends GuiceOneAppPerTest { this: TestSuite =>
trait OneAppPerTest extends GuiceOneAppPerTest { this: Suite =>

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import scala.util.Try
/**
* Trait that provides a new Selenium `WebDriver` instance per ScalaTest `Suite`.
*
* This `TestSuiteMixin` trait's overridden `run` method
* This `SuiteMixin` trait's overridden `run` method
* places a reference to the `WebDriver` provided by `webDriver` under the key `org.scalatestplus.play.webDriver`.
* This allows any nested `Suite`s to access the `Suite`'s
* `WebDriver` as well, most easily by having the nested `Suite`s mix in the
Expand Down Expand Up @@ -305,11 +305,12 @@ import scala.util.Try
* </pre>
*/
trait OneBrowserPerSuite
extends TestSuiteMixin
extends SuiteMixin
with BeforeAndAfterEach
with WebBrowser
with Eventually
with IntegrationPatience
with BrowserFactory { this: TestSuite with ServerProvider =>
with BrowserFactory { this: Suite with ServerProvider =>

/**
* An implicit instance of `WebDriver`, created by calling `createWebDriver`.
Expand All @@ -322,14 +323,14 @@ trait OneBrowserPerSuite
* Automatically cancels tests with an appropriate error message when the `webDriver` field is a `UnavailableDriver`,
* else calls `super.withFixture(test)`
*/
abstract override def withFixture(test: NoArgTest): Outcome = {
override def beforeEach(): Unit = {
webDriver match {
case UnavailableDriver(ex, errorMessage) =>
ex match {
case Some(e) => cancel(errorMessage, e)
case None => cancel(errorMessage)
}
case _ => super.withFixture(test)
case _ => super.beforeEach()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,12 @@ import org.scalatestplus.selenium.WebBrowser
* </pre>
*/
trait OneBrowserPerTest
extends TestSuiteMixin
extends SuiteMixin
with BeforeAndAfterEach
with WebBrowser
with Eventually
with IntegrationPatience
with BrowserFactory { this: TestSuite with ServerProvider =>
with BrowserFactory { this: Suite with ServerProvider =>

private var privateWebDriver: WebDriver = UninitializedDriver

Expand All @@ -110,22 +111,24 @@ trait OneBrowserPerTest
* If an error occurs when attempting to creat the `WebDriver`, [[org.scalatestplus.play.BrowserFactory.UnavailableDriver BrowserFactory.UnavailableDriver]]
* will be used instead and all tests will be canceled automatically.
*
* @param test the no-arg test function to run with a fixture
* @return the `Outcome` of the test execution
*/
abstract override def withFixture(test: NoArgTest) = {
override def beforeEach(): Unit = {
synchronized {
privateWebDriver = createWebDriver()
}
privateWebDriver match {
case UnavailableDriver(ex, errorMessage) =>
ex match {
case Some(e) => cancel(errorMessage, e)
case None => cancel(errorMessage)
}
case _ => super.beforeEach()
}
}

override def afterEach(): Unit = {
try {
privateWebDriver match {
case UnavailableDriver(ex, errorMessage) =>
ex match {
case Some(e) => cancel(errorMessage, e)
case None => cancel(errorMessage)
}
case _ => super.withFixture(test)
}
super.afterEach()
} finally {
privateWebDriver match {
case _: UnavailableDriver => // do nothing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
*/
package org.scalatestplus.play

import org.scalatest.TestSuite
import org.scalatest.Suite
import org.scalatestplus.play.guice.GuiceOneServerPerSuite

/**
* Synonym for GuiceOneServerPerSuite.
*/
@deprecated("Use GuiceOneServerPerSuite instead", "2.0.0")
trait OneServerPerSuite extends GuiceOneServerPerSuite { this: TestSuite =>
trait OneServerPerSuite extends GuiceOneServerPerSuite { this: Suite =>

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ import org.scalatestplus.play.guice.GuiceOneServerPerTest
* Synonym for GuiceOneServerPerTest
*/
@deprecated("Use GuiceOneServerPerTest instead", "2.0.0")
trait OneServerPerTest extends GuiceOneServerPerTest { this: TestSuite =>
trait OneServerPerTest extends GuiceOneServerPerTest { this: Suite =>

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.scalatestplus.play.components

import org.scalatest.TestSuite
import org.scalatest.Suite
import org.scalatestplus.play.BaseOneAppPerSuite
import org.scalatestplus.play.FakeApplicationFactory
import play.api.Application
Expand All @@ -12,7 +12,7 @@ import play.api.Application
*
* By default, this trait creates a new `Application` for the `Suite` according to the components defined in the test.
*
* This `TestSuiteMixin` trait's overridden `run` method calls `Play.start`, passing in the
* This `SuiteMixin` trait's overridden `run` method calls `Play.start`, passing in the
* `Application` provided by `app`, before executing the `Suite` via a call to `super.run`.
* In addition, it places a reference to the `Application` provided by `app` into the `ConfigMap`
* under the key `org.scalatestplus.play.app`. This allows any nested `Suite`s to access the `Suite`'s
Expand Down Expand Up @@ -70,7 +70,7 @@ import play.api.Application
* `Suite`s. Annotate the nested suites with `@DoNotDiscover` and have them extend `ConfiguredApp`. Here's an example:
*
* <pre class="stHighlight">
* import org.scalatest.{DoNotDiscover, Suites, TestSuite}
* import org.scalatest.{DoNotDiscover, Suites, Suite}
* import org.scalatestplus.play.components.OneAppPerSuiteWithComponents
* import org.scalatestplus.play.{ConfiguredApp, PlaySpec}
* import play.api._
Expand All @@ -86,7 +86,7 @@ import play.api.Application
* new TwoSpec,
* new RedSpec,
* new BlueSpec
* ) with OneAppPerSuiteWithComponents with TestSuite {
* ) with OneAppPerSuiteWithComponents with Suite {
* // Override fakeApplication if you need an Application with other than non-default parameters.
* override def components: BuiltInComponents = new BuiltInComponentsFromContext(context) with NoHttpFiltersComponents {
*
Expand Down Expand Up @@ -137,7 +137,7 @@ trait OneAppPerSuiteWithComponents
extends BaseOneAppPerSuite
with WithApplicationComponents
with FakeApplicationFactory {
this: TestSuite =>
this: Suite =>

override def fakeApplication(): Application = newApplication
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.scalatestplus.play.components

import org.scalatest.TestSuite
import org.scalatest.TestSuiteMixin
import org.scalatest.Suite
import org.scalatest.SuiteMixin
import org.scalatestplus.play.BaseOneAppPerTest
import org.scalatestplus.play.FakeApplicationFactory
import play.api.Application
Expand All @@ -11,7 +11,7 @@ import play.api.Application
*
* Trait that provides a new `Application` instance for each test.
*
* This `TestSuiteMixin` trait's overridden `withFixture` method creates a new `Application`
* This `SuiteMixin` trait's overridden `withFixture` method creates a new `Application`
* before each test and ensures it is cleaned up after the test has completed. You can
* access the `Application` from your tests as method `app` (which is marked implicit).
*
Expand Down Expand Up @@ -63,8 +63,8 @@ trait OneAppPerTestWithComponents
extends BaseOneAppPerTest
with WithApplicationComponents
with FakeApplicationFactory
with TestSuiteMixin {
this: TestSuite =>
with SuiteMixin {
this: Suite =>

override def fakeApplication(): Application = newApplication
}
Loading

0 comments on commit ce6a5f9

Please sign in to comment.