aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jakob@driver.xyz>2018-10-09 14:37:57 -0700
committerJakob Odersky <jakob@odersky.com>2018-10-09 16:19:39 -0700
commit46d7e38b4651caff2a7fb9dc9ee1aa398807db44 (patch)
tree8939ecc030442069e4938c5e59b53fa91e486c81
parentd858e1ca733407aeeb39d9d85edb26373443a9b9 (diff)
downloaddriver-core-46d7e38b4651caff2a7fb9dc9ee1aa398807db44.tar.gz
driver-core-46d7e38b4651caff2a7fb9dc9ee1aa398807db44.tar.bz2
driver-core-46d7e38b4651caff2a7fb9dc9ee1aa398807db44.zip
Add testkit modulev2.0.0-M2
-rw-r--r--README.md1
-rw-r--r--build.sbt19
-rw-r--r--core-testkit/src/main/scala/akka/http/scaladsl/testkit/TestRouteServiceTransport.scala79
-rw-r--r--core-testkit/src/main/scala/xyz/driver/core/testkit/AsyncDatabaseBackedRouteTest.scala28
-rw-r--r--core-testkit/src/main/scala/xyz/driver/core/testkit/DriverFunctionalTest.scala18
-rw-r--r--core-testkit/src/main/scala/xyz/driver/core/testkit/FixtureDatabase.scala60
-rw-r--r--core-testkit/src/main/scala/xyz/driver/core/testkit/RestDatabaseResetService.scala70
-rw-r--r--core-testkit/src/main/scala/xyz/driver/core/testkit/hsql/HsqlTestDatabase.scala26
-rw-r--r--core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresDatabase.scala46
-rw-r--r--core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresFixtureDatabase.scala74
-rw-r--r--core-testkit/src/main/scala/xyz/driver/test/renames.scala46
11 files changed, 465 insertions, 2 deletions
diff --git a/README.md b/README.md
index c44f820..22cecd0 100644
--- a/README.md
+++ b/README.md
@@ -49,6 +49,7 @@ Project | Description
`core-reporting` | Combined tracing and logging library.
`core-rest` | Abstractions to represent RESTful services, discovery and client implementations.
`core-storage` | Object storage utilities.
+`core-testkit` | Mixins for scalatest.
`core-types` | Type definitions that are commonly used by applications.
`core-util` | Other utilities that do not belong anywhere else. **Note that this is a staging place for code that does not have its own submodule yet. Do not depend on it externally!**
diff --git a/build.sbt b/build.sbt
index fdba59e..286e7ec 100644
--- a/build.sbt
+++ b/build.sbt
@@ -11,6 +11,9 @@ scalacOptions in ThisBuild in (Compile, doc) ++= Seq(
s"https://github.com/drivergroup/driver-core/blob/master€{FILE_PATH}.scala"
)
+val mockito = "org.mockito" % "mockito-core" % "1.9.5"
+val scalatest = "org.scalatest" %% "scalatest" % "3.0.5"
+
// TODO these shouldn't be declared in the build scope. They should be moved to the individual
// sub-projects that actually depend on them.
libraryDependencies in ThisBuild ++= Seq(
@@ -44,11 +47,11 @@ libraryDependencies in ThisBuild ++= Seq(
"io.kamon" %% "kamon-statsd" % "1.0.0",
"io.kamon" %% "kamon-system-metrics" % "1.0.0",
"javax.xml.bind" % "jaxb-api" % "2.2.8",
- "org.mockito" % "mockito-core" % "1.9.5" % "test",
+ mockito % "test",
"org.scala-lang.modules" %% "scala-async" % "0.9.7",
"org.scalacheck" %% "scalacheck" % "1.14.0" % "test",
- "org.scalatest" %% "scalatest" % "3.0.5" % "test",
"org.scalaz" %% "scalaz-core" % "7.2.24",
+ scalatest % "test",
"xyz.driver" %% "spray-json-derivation" % "0.6.0",
"xyz.driver" %% "tracing" % "0.1.2"
)
@@ -84,6 +87,18 @@ lazy val `core-init` = project
.enablePlugins(LibraryPlugin)
.dependsOn(`core-reporting`, `core-storage`, `core-messaging`, `core-rest`, `core-database`)
+lazy val `core-testkit` = project
+ .enablePlugins(LibraryPlugin)
+ .dependsOn(`core-rest`, `core-database`)
+ .settings(
+ libraryDependencies ++= Seq(
+ "com.spotify" % "docker-client" % "8.11.7" classifier "shaded",
+ "org.postgresql" % "postgresql" % "9.4.1212",
+ "org.scalamock" %% "scalamock-scalatest-support" % "3.6.0",
+ scalatest
+ )
+ )
+
lazy val core = project
.in(file("."))
.enablePlugins(LibraryPlugin)
diff --git a/core-testkit/src/main/scala/akka/http/scaladsl/testkit/TestRouteServiceTransport.scala b/core-testkit/src/main/scala/akka/http/scaladsl/testkit/TestRouteServiceTransport.scala
new file mode 100644
index 0000000..36e3596
--- /dev/null
+++ b/core-testkit/src/main/scala/akka/http/scaladsl/testkit/TestRouteServiceTransport.scala
@@ -0,0 +1,79 @@
+package akka.http.scaladsl.testkit
+
+import akka.actor.ActorSystem
+import akka.http.javadsl.testkit.DefaultHostInfo
+import akka.http.scaladsl.model._
+import akka.http.scaladsl.model.headers.{Host, RawHeader}
+import akka.http.scaladsl.server._
+import akka.http.scaladsl.settings.RoutingSettings
+import akka.http.scaladsl.unmarshalling.Unmarshal
+import akka.stream.{ActorMaterializer, Materializer}
+import org.slf4j.MDC
+import xyz.driver.core.rest.errors.ExternalServiceException
+import xyz.driver.core.rest.{ContextHeaders, ServiceRequestContext, ServiceTransport}
+
+import scala.concurrent.{ExecutionContextExecutor, Future}
+import scala.concurrent.duration._
+
+class TestRouteServiceTransport(route: Route, routeTimeout: FiniteDuration = 10 seconds)(
+ implicit executor: ExecutionContextExecutor,
+ system: ActorSystem)
+ extends ServiceTransport with RouteTestResultComponent {
+
+ def defaultHost: DefaultHostInfo = DefaultHostInfo(Host("example.com"), securedConnection = false)
+ def routingLog: RoutingLog = RoutingLog(system.log)
+ def routingSettings: RoutingSettings = RoutingSettings.apply(system)
+ implicit val materializer = ActorMaterializer()
+
+ override def sendRequestGetResponse(context: ServiceRequestContext)(
+ requestStub: HttpRequest): Future[HttpResponse] = {
+
+ val request = requestStub
+ .withHeaders(requestStub.headers ++ context.contextHeaders.toSeq.map {
+ case (ContextHeaders.TrackingIdHeader, _) =>
+ RawHeader(ContextHeaders.TrackingIdHeader, context.trackingId)
+ case (ContextHeaders.StacktraceHeader, _) =>
+ RawHeader(
+ ContextHeaders.StacktraceHeader,
+ Option(MDC.get("stack"))
+ .orElse(context.contextHeaders.get(ContextHeaders.StacktraceHeader))
+ .getOrElse(""))
+ case (header, headerValue) => RawHeader(header, headerValue)
+ }: _*)
+
+ // Code below is forked from `akka.http.scaladsl.testkit.RouteTest.TildeArrow.injectIntoRoute`,
+ // because it doesn't allow to call just this code outside of the DSL for testkit tests
+ val routeTestResult = new RouteTestResult(routeTimeout)
+
+ val effectiveRequest = request
+
+ val log = routingLog.requestLog(effectiveRequest)
+ val ctx = new RequestContextImpl(effectiveRequest, log, routingSettings)(executor, materializer)
+ val sealedExceptionHandler = ExceptionHandler.default(routingSettings)
+ val semiSealedRoute = Directives.handleExceptions(sealedExceptionHandler)(route)
+ val deferrableRouteResult = semiSealedRoute(ctx)
+
+ deferrableRouteResult.map(r => { routeTestResult.handleResult(r); routeTestResult.response })
+ }
+
+ override def sendRequest(context: ServiceRequestContext)(requestStub: HttpRequest)(
+ implicit mat: Materializer): Future[Unmarshal[ResponseEntity]] = {
+ sendRequestGetResponse(context)(requestStub) flatMap { response =>
+ if (response.status == StatusCodes.NotFound) {
+ Future.successful(Unmarshal(HttpEntity.Empty: ResponseEntity))
+ } else if (response.status.isFailure()) {
+ val serviceCalled = s"${requestStub.method} ${requestStub.uri}"
+ Unmarshal(response.entity).to[String] flatMap { errorString =>
+ import spray.json._
+ import xyz.driver.core.json._
+ val serviceException = scala.util.Try(serviceExceptionFormat.read(errorString.parseJson)).toOption
+ Future.failed(ExternalServiceException(serviceCalled, errorString, serviceException))
+ }
+ } else {
+ Future.successful(Unmarshal(response.entity))
+ }
+ }
+ }
+
+ override def failTest(msg: String): Nothing = throw new Exception(msg)
+}
diff --git a/core-testkit/src/main/scala/xyz/driver/core/testkit/AsyncDatabaseBackedRouteTest.scala b/core-testkit/src/main/scala/xyz/driver/core/testkit/AsyncDatabaseBackedRouteTest.scala
new file mode 100644
index 0000000..8ce33f6
--- /dev/null
+++ b/core-testkit/src/main/scala/xyz/driver/core/testkit/AsyncDatabaseBackedRouteTest.scala
@@ -0,0 +1,28 @@
+package xyz.driver.core.testkit
+
+import java.util.concurrent.Executors
+
+import akka.actor.ActorSystem
+import akka.http.scaladsl.server.directives.FutureDirectives
+import akka.http.scaladsl.testkit.{RouteTestTimeout, ScalatestRouteTest}
+import org.scalamock.scalatest.AsyncMockFactory
+import org.scalatest.AsyncFlatSpec
+
+import scala.concurrent.duration._
+import scala.concurrent.{ExecutionContext, ExecutionContextExecutor}
+
+trait AsyncDatabaseBackedRouteTest
+ extends AsyncFlatSpec with DriverFunctionalTest with AsyncMockFactory with ScalatestRouteTest {
+
+ def route: FutureDirectives
+
+ val defaultTimeOut: FiniteDuration = 5.seconds
+ implicit def default(implicit system: ActorSystem): RouteTestTimeout = RouteTestTimeout(defaultTimeOut)
+
+ override implicit val executor: ExecutionContextExecutor =
+ ExecutionContext.fromExecutor(Executors.newFixedThreadPool(4))
+ override implicit def executionContext: ExecutionContext = executor
+
+ override def beforeAll: Unit = super.beforeAll()
+ override def afterAll: Unit = super.afterAll()
+}
diff --git a/core-testkit/src/main/scala/xyz/driver/core/testkit/DriverFunctionalTest.scala b/core-testkit/src/main/scala/xyz/driver/core/testkit/DriverFunctionalTest.scala
new file mode 100644
index 0000000..f4c793b
--- /dev/null
+++ b/core-testkit/src/main/scala/xyz/driver/core/testkit/DriverFunctionalTest.scala
@@ -0,0 +1,18 @@
+package xyz.driver.core.testkit
+
+import com.typesafe.scalalogging.Logger
+import org.scalatest.{Matchers, Suite}
+import org.slf4j.helpers.NOPLogger
+import xyz.driver.core.time.Time
+import xyz.driver.core.time.provider.{SpecificTimeProvider, TimeProvider}
+
+trait DriverFunctionalTest extends Matchers with postgres.DockerPostgresFixtureDatabase {
+ self: Suite =>
+
+ // Needed to reset some external libraries timezones (e.g., HSQLDB)
+ // for local development matching CI and deployed environment
+ java.util.TimeZone.setDefault(java.util.TimeZone.getTimeZone("Etc/UTC"))
+
+ val log: Logger = Logger(NOPLogger.NOP_LOGGER)
+ val timeProvider: TimeProvider = new SpecificTimeProvider(Time(100000))
+}
diff --git a/core-testkit/src/main/scala/xyz/driver/core/testkit/FixtureDatabase.scala b/core-testkit/src/main/scala/xyz/driver/core/testkit/FixtureDatabase.scala
new file mode 100644
index 0000000..aa07668
--- /dev/null
+++ b/core-testkit/src/main/scala/xyz/driver/core/testkit/FixtureDatabase.scala
@@ -0,0 +1,60 @@
+package xyz.driver.core.testkit
+
+import java.nio.file.{Files, Path}
+
+import scala.concurrent.Await
+import scala.concurrent.duration._
+
+import org.scalatest.{BeforeAndAfterEach, Suite}
+import slick.basic.BasicProfile
+import slick.jdbc.JdbcProfile
+import slick.relational.RelationalProfile
+
+trait FixtureDatabase[P <: BasicProfile] { self: Suite =>
+ val profile: P
+ val database: P#Backend#DatabaseDef
+}
+
+trait CreateAndDropSchemaForEach[P <: RelationalProfile] extends BeforeAndAfterEach {
+ self: Suite with FixtureDatabase[P] =>
+ import profile.api._
+ def schema: profile.SchemaDescription
+
+ override protected def beforeEach() = {
+ Await.result(database.run(schema.create), 5.seconds)
+ super.beforeEach()
+ }
+
+ override protected def afterEach() = {
+ try super.afterEach()
+ finally Await.result(database.run(schema.drop), 5.seconds)
+ }
+}
+
+trait TruncateSchemaAfterEach[P <: RelationalProfile] extends BeforeAndAfterEach {
+ self: Suite with FixtureDatabase[P] =>
+ import profile.api._
+
+ def schema: profile.SchemaDescription
+
+ override protected def afterEach() = {
+ try super.afterEach()
+ finally Await.result(database.run(schema.truncate), 5.seconds)
+ }
+}
+
+trait InsertBeforeEach[P <: JdbcProfile] extends BeforeAndAfterEach { self: Suite with FixtureDatabase[P] =>
+ import profile.api._
+
+ val insertsFiles: Set[Path]
+
+ def insertTestData(insertsFile: Path): DBIO[Int] = {
+ val rawInserts = new String(Files.readAllBytes(insertsFile), "UTF-8")
+ sql"#$rawInserts".asUpdate
+ }
+
+ override protected def beforeEach(): Unit = {
+ concurrent.Await.result(database.run(DBIO.sequence(insertsFiles.toList.map(insertTestData))), 30.seconds)
+ super.beforeEach()
+ }
+}
diff --git a/core-testkit/src/main/scala/xyz/driver/core/testkit/RestDatabaseResetService.scala b/core-testkit/src/main/scala/xyz/driver/core/testkit/RestDatabaseResetService.scala
new file mode 100644
index 0000000..db02bbb
--- /dev/null
+++ b/core-testkit/src/main/scala/xyz/driver/core/testkit/RestDatabaseResetService.scala
@@ -0,0 +1,70 @@
+package xyz.driver.core.testkit
+
+import akka.actor.ActorSystem
+import akka.http.scaladsl.model._
+import akka.stream.ActorMaterializer
+import spray.json._
+import xyz.driver.core.Name
+import xyz.driver.core.rest.{RestService, ServiceRequestContext, ServiceTransport}
+
+import scala.concurrent.{ExecutionContext, Future}
+import scalaz.{ListT, OptionT}
+
+object RestDatabaseResetService {
+ import DefaultJsonProtocol._
+ import xyz.driver.core.json._
+
+ final case class Application(name: Name[Application], tag: String)
+
+ final case class Environment(name: Name[Environment], applications: Seq[Application], status: String)
+
+ implicit val applicationJsonFormat = jsonFormat2(Application)
+
+ implicit val environmentJsonFormat = jsonFormat3(Environment)
+}
+
+class RestDatabaseResetService(
+ transport: ServiceTransport,
+ baseUri: Uri,
+ actorSystem: ActorSystem,
+ executionContext: ExecutionContext)
+ extends RestService {
+
+ import DefaultJsonProtocol._
+ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+ import RestDatabaseResetService._
+
+ protected implicit val exec = executionContext
+ protected implicit val materializer = ActorMaterializer()(actorSystem)
+
+ def getAvailableEnvironments(): ListT[Future, String] = {
+ val request = get(baseUri, s"/v1/environment")
+ listResponse[String](transport.sendRequest(new ServiceRequestContext())(request))
+ }
+
+ def getEnvironmentDetails(envName: Name[Environment]): ListT[Future, Environment] = {
+ val requestStub = get(baseUri, s"/v1/environment/$envName")
+ listResponse[Environment](transport.sendRequest(new ServiceRequestContext())(requestStub))
+ }
+
+ def getEnvironmentStatus(envName: Name[Environment]): OptionT[Future, String] = {
+ val requestStub = get(baseUri, s"/v1/environment/$envName/status")
+ optionalResponse[String](transport.sendRequest(new ServiceRequestContext())(requestStub))
+ }
+
+ def resetEnvironmentStatus(envName: Name[Environment], newStatus: String): OptionT[Future, String] = {
+ val requestStub = HttpRequest(HttpMethods.POST, endpointUri(baseUri, s"/v1/environment/$envName/status"))
+ optionalResponse[String](transport.sendRequest(new ServiceRequestContext())(requestStub))
+ }
+
+ def resetEnvironmentApplicationsData(envName: Name[Environment]): OptionT[Future, Unit] = {
+ val requestStub = HttpRequest(HttpMethods.POST, endpointUri(baseUri, s"/v1/environment/$envName/reset"))
+ unitResponse(transport.sendRequest(new ServiceRequestContext())(requestStub))
+ }
+
+ def updateEnvironmentState(updatedEnvironment: Environment)(
+ implicit ctx: ServiceRequestContext): OptionT[Future, Environment] = {
+ val requestStub = postJson(baseUri, s"/v1/environment/${updatedEnvironment.name}", updatedEnvironment.toJson)
+ optionalResponse[Environment](transport.sendRequest(ctx)(requestStub))
+ }
+}
diff --git a/core-testkit/src/main/scala/xyz/driver/core/testkit/hsql/HsqlTestDatabase.scala b/core-testkit/src/main/scala/xyz/driver/core/testkit/hsql/HsqlTestDatabase.scala
new file mode 100644
index 0000000..8a4c3e8
--- /dev/null
+++ b/core-testkit/src/main/scala/xyz/driver/core/testkit/hsql/HsqlTestDatabase.scala
@@ -0,0 +1,26 @@
+package xyz.driver.test.hsql
+
+import java.nio.file.{Files, Paths}
+
+import slick.dbio.DBIO
+
+trait HsqlTestDatabase {
+ def insertTestData(database: xyz.driver.core.database.Database, filePath: String): DBIO[Int] = {
+ import database.profile.api._
+
+ val file = Paths.get(filePath)
+ val sqlLine = new String(Files.readAllBytes(file), "UTF-8")
+
+ val createProcedure =
+ sqlu"""CREATE PROCEDURE INSERT_TEST_DATA()
+ MODIFIES SQL DATA
+ BEGIN ATOMIC
+ #$sqlLine
+ END;
+ """
+ val callProcedure = sqlu"""{call INSERT_TEST_DATA()}"""
+ val dropProcedure = sqlu"""drop PROCEDURE INSERT_TEST_DATA;"""
+
+ createProcedure >> callProcedure >> dropProcedure
+ }
+}
diff --git a/core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresDatabase.scala b/core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresDatabase.scala
new file mode 100644
index 0000000..41e6e0d
--- /dev/null
+++ b/core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresDatabase.scala
@@ -0,0 +1,46 @@
+package xyz.driver.core.testkit
+package postgres
+
+import xyz.driver.core.make
+
+trait DockerPostgresDatabase {
+ import com.spotify.docker.client._
+ import com.spotify.docker.client.messages._
+
+ lazy val dockerClient: DockerClient = DefaultDockerClient.fromEnv().build()
+
+ val postgresVersion: String = "9.6"
+
+ def setupDockerDatabase(
+ username: String = "postgres",
+ password: String = "postgres",
+ database: String = "postgres",
+ hostPort: Int = 15432): String = {
+ import collection.JavaConverters._
+
+ dockerClient.pull(s"postgres:$postgresVersion")
+
+ val portBindings: Map[String, List[PortBinding]] = Map("5432" -> List(PortBinding.of("0.0.0.0", hostPort)))
+ val portBindingsJava = portBindings.mapValues(_.asJava).asJava
+ val hostConfig = HostConfig.builder().portBindings(portBindingsJava).build()
+ val containerConfig =
+ ContainerConfig
+ .builder()
+ .hostConfig(hostConfig)
+ .image(s"postgres:$postgresVersion")
+ .exposedPorts("5432")
+ .env(
+ s"POSTGRES_USER=$username",
+ s"POSTGRES_DB=$database",
+ s"POSTGRES_PASSWORD=$password"
+ )
+ .build()
+
+ make(dockerClient.createContainer(containerConfig).id())(dockerClient.startContainer)
+ }
+
+ def killDockerDatabase(containerId: String): Unit = {
+ dockerClient.killContainer(containerId)
+ dockerClient.removeContainer(containerId)
+ }
+}
diff --git a/core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresFixtureDatabase.scala b/core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresFixtureDatabase.scala
new file mode 100644
index 0000000..3e00bf5
--- /dev/null
+++ b/core-testkit/src/main/scala/xyz/driver/core/testkit/postgres/DockerPostgresFixtureDatabase.scala
@@ -0,0 +1,74 @@
+package xyz.driver.core.testkit
+package postgres
+
+import java.net.ServerSocket
+
+import org.scalatest.{BeforeAndAfterAll, Suite}
+import slick.jdbc.PostgresProfile
+import xyz.driver.core.using
+
+import scala.concurrent.Await
+import scala.concurrent.duration._
+
+trait DockerPostgresFixtureDatabase
+ extends FixtureDatabase[PostgresProfile] with DockerPostgresDatabase with BeforeAndAfterAll {
+ self: Suite =>
+ private val dbName: String = sys.env.getOrElse("TEST_DB_NAME", "postgres")
+ private val username: String = sys.env.getOrElse("TEST_DB_USERNAME", "postgres")
+ private val password: String = sys.env.getOrElse("TEST_DB_PASSWORD", "postgres")
+ private val port: Int = sys.env.get("TEST_DB_PORT").fold(getRandomPort())(_.toInt)
+
+ private val enabled: Boolean = !sys.env.get("DISABLE_DOCKER_TEST_DB").contains("true")
+
+ protected val connectionTimeout: Duration = 16.seconds
+
+ final val profile = PostgresProfile
+ final override val database = profile.backend.Database.forURL(
+ driver = "org.postgresql.Driver",
+ url = s"jdbc:postgresql://localhost:$port/$dbName",
+ user = username,
+ password = password)
+
+ object driverDatabase extends xyz.driver.core.database.Database {
+ override val profile = self.profile
+ override val database = self.database
+ }
+
+ private def getRandomPort(): Int = using(new ServerSocket(0))(_.getLocalPort())
+
+ @SuppressWarnings(Array("org.wartremover.warts.Var"))
+ private var dockerContainerId: Option[String] = None
+
+ private def waitForContainer(): Unit = {
+ import concurrent.ExecutionContext.Implicits.global
+ import profile.api._
+
+ val expiration = System.currentTimeMillis() + connectionTimeout.toMillis
+
+ val query = sql"SELECT 1;".as[Int]
+ def dbReady = Await.result(
+ database
+ .run(query)
+ .map(_ == Vector(1))
+ .recover({ case _: org.postgresql.util.PSQLException => false }),
+ connectionTimeout
+ )
+
+ while (!dbReady && System.currentTimeMillis() < expiration) {
+ Thread.sleep(100)
+ }
+ }
+
+ override protected def beforeAll(): Unit = {
+ if (enabled) {
+ dockerContainerId = Some(super.setupDockerDatabase(username, password, dbName, port))
+ waitForContainer()
+ }
+ super.beforeAll()
+ }
+
+ override protected def afterAll(): Unit = {
+ try super.afterAll()
+ finally dockerContainerId.foreach(killDockerDatabase)
+ }
+}
diff --git a/core-testkit/src/main/scala/xyz/driver/test/renames.scala b/core-testkit/src/main/scala/xyz/driver/test/renames.scala
new file mode 100644
index 0000000..0ebee4a
--- /dev/null
+++ b/core-testkit/src/main/scala/xyz/driver/test/renames.scala
@@ -0,0 +1,46 @@
+package xyz.driver
+
+import xyz.driver.core.testkit
+import slick.basic.BasicProfile
+import slick.jdbc.JdbcProfile
+import slick.relational.RelationalProfile
+
+package object test {
+
+ @deprecated("moved to package `xyz.driver.core.testkit`", "2.0")
+ type AsyncDatabaseBackedRouteTest = testkit.AsyncDatabaseBackedRouteTest
+
+ @deprecated("moved to package `xyz.driver.core.testkit`", "2.0")
+ type DriverFunctionalTest = testkit.DriverFunctionalTest
+
+ @deprecated("moved to package `xyz.driver.core.testkit`", "2.0")
+ type FixtureDatabase[P <: BasicProfile] = testkit.FixtureDatabase[P]
+
+ @deprecated("moved to package `xyz.driver.core.testkit`", "2.0")
+ type CreateAndDropSchemaForEach[P <: RelationalProfile] = testkit.CreateAndDropSchemaForEach[P]
+
+ @deprecated("moved to package `xyz.driver.core.testkit`", "2.0")
+ type TruncateSchemaAfterEach[P <: RelationalProfile] = testkit.TruncateSchemaAfterEach[P]
+
+ @deprecated("moved to package `xyz.driver.core.testkit`", "2.0")
+ type InsertBeforeEach[P <: JdbcProfile] = testkit.InsertBeforeEach[P]
+
+ @deprecated("moved to package `xyz.driver.core.testkit`", "2.0")
+ type RestDatabaseResetService = testkit.RestDatabaseResetService
+
+ @deprecated("moved to package `xyz.driver.core.testkit`", "2.0")
+ val RestDatabaseResetService: testkit.RestDatabaseResetService.type = testkit.RestDatabaseResetService
+
+}
+
+package test {
+ package object postgres {
+
+ @deprecated("moved to package `xyz.driver.core.testkit.postgres`", "2.0")
+ type DockerPostgresDatabase = xyz.driver.core.testkit.postgres.DockerPostgresDatabase
+
+ @deprecated("moved to package `xyz.driver.core.testkit.postgres`", "2.0")
+ type DockerPostgresFixtureDatabase = xyz.driver.core.testkit.postgres.DockerPostgresFixtureDatabase
+
+ }
+}