Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala sbt test run setup and cleanup command once on multi project

I know I can add setup and cleanup code in sbt for the test phase by modifying the testOptions, e.g.:

  val embedMongoTestSettings: Seq[Setting[_]] = Seq(
    testOptions in Test += Tests.Setup( () => createMongod()),
    testOptions in Test += Tests.Cleanup( () => destroyMongod())
  )

The problem I have is that this done on a per project basis and then done once for every project. So when I have a multi project set up, I fire up several databases in this case (which would work, but means I have to configure per project ports, etc.).

Is there a way within sbt that makes sure that certain steps are only run once per any test phase, no matter if it is for multi projects, one project or a single test case?

Only way I figure is to manage the concurrency myself in the setup and cleanup parts, so keep a global counter that checks if it is the first one started or last one torn down.

like image 235
Elmar Weber Avatar asked Nov 01 '22 13:11

Elmar Weber


1 Answers

I wrote a blog post on sequencing tasks, which you might find it useful.

If you want to aggregate tests and make sure things are sequenced, one quick way of doing that is making a custom command. The following defines a command alias called sts:

lazy val commonSettings = Seq(
  scalaVersion := "2.11.4"
)
lazy val specs2Core = "org.specs2" %% "specs2-core" % "2.4.15"
val startTest = taskKey[Unit]("start test")
val stopTest = taskKey[Unit]("stop test")

lazy val root = (project in file(".")).
  aggregate(app, webapp).
  settings(commonSettings: _*).
  settings(addCommandAlias("sts", ";startTest;test;stopTest"): _*).
  settings(
    startTest in ThisBuild := {
      println("starting server...")
      Thread.sleep(500)
    },
    stopTest in ThisBuild := {
      println("stopping server...")
      Thread.sleep(500)
    }
  )

lazy val app = (project in file("app")).
  settings(commonSettings: _*).
  settings(
    libraryDependencies += specs2Core % Test
  )

lazy val webapp = (project in file("webapp")).
  settings(commonSettings: _*).
  settings(
    libraryDependencies += specs2Core % Test
  )

You can substitute the implementation of startTest in ThisBuild and stopTest in ThisBuild as you like. By defining these settings at the ThisBuild level, sts command should work at both the root level as well as at individual subproject level.

root> sts
starting server...
[success] Total time: 1 s, completed Jan 13, 2015 5:20:58 PM
[info] HelloWorldSpec
....
[info] Passed: Total 3, Failed 0, Errors 0, Passed 3
[success] Total time: 1 s, completed Jan 13, 2015 5:20:59 PM
stopping server...
[success] Total time: 1 s, completed Jan 13, 2015 5:20:59 PM 
root> project app
[info] Set current project to app
app> sts
starting server...
[success] Total time: 1 s, completed Jan 13, 2015 5:21:15 PM
[info] HelloWorldSpec
....
[info] Passed: Total 3, Failed 0, Errors 0, Passed 3
[success] Total time: 1 s, completed Jan 13, 2015 5:21:16 PM
stopping server...
[success] Total time: 1 s, completed Jan 13, 2015 5:21:16 PM
like image 50
Eugene Yokota Avatar answered Nov 15 '22 06:11

Eugene Yokota