39

I would like to share a helper trait between my "test" and "it" configurations in SBT, but I have not figured out how.

Here is a minimal example:

project/Build.scala

import sbt._
import Keys._

object MyBuild extends Build {

  val scalaTest = "org.scalatest" %% "scalatest" % "2.0" % "test,it"

  lazy val myProject =
    Project(id = "my-project", base = file("."))
      .configs(IntegrationTest)
      .settings(Defaults.itSettings: _*)
      .settings(
        scalaVersion := "2.10.3",
        libraryDependencies ++= Seq(
          scalaTest
        )
      )
}

src/test/scala/Helpers.scala

trait Helper {
  def help() { println("helping.") }
}

src/test/scala/TestSuite.scala

import org.scalatest._

class TestSuite extends FlatSpec with Matchers with Helper {
  "My code" should "work" in {
    help()
    true should be(true)
  }
}

src/it/scala/ItSuite.scala

import org.scalatest._

class ItSuite extends FlatSpec with Matchers with Helper {
  "My code" should "work" in {
    help()
    true should be(true)
  }
}

then, in sbt, "test" works:

sbt> test
helping.
[info] TestSuite:
[info] My code
[info] - should work
[info] Run completed in 223 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 0 s, completed Dec 17, 2013 1:54:56 AM

but "it:test" doesn't compile:

sbt> it:test
[info] Compiling 1 Scala source to ./target/scala-2.10/it-classes...
[error] ./src/it/scala/ItSuite.scala:3: not found: type Helper
[error] class ItSuite extends FlatSpec with Matchers with Helper {
[error]                                                   ^
[error] ./src/it/scala/ItSuite.scala:5: not found: value help
[error]     help()
[error]     ^
[error] two errors found
[error] (it:compile) Compilation failed
[error] Total time: 1 s, completed Dec 17, 2013 1:55:00 AM
pfm
  • 6,210
  • 4
  • 39
  • 44
Rob Starling
  • 3,868
  • 3
  • 23
  • 40

2 Answers2

20

You can redefine the IntegrationTest Configuration in your project to extend the Test configuration instead of the Runtime Configuration (the default). This will make everything in your test configuration available to your IntegrationTest configuration.

import sbt._
import Keys._

object MyBuild extends Build {

  val scalaTest = "org.scalatest" %% "scalatest" % "2.0" % "test,it"

  lazy val IntegrationTest = config("it") extend(Test)

  lazy val myProject =
    Project(id = "my-project", base = file("."))
      .configs(IntegrationTest)
      .settings(Defaults.itSettings: _*)
      .settings(
        scalaVersion := "2.10.3",
        libraryDependencies ++= Seq(
          scalaTest
        )
      )
}
pfm
  • 6,210
  • 4
  • 39
  • 44
Caoilte
  • 2,381
  • 1
  • 21
  • 27
  • if i do that, aren't there weird gotchas lurking if some other part of the build config sees the shadowed "real" `IntegrationTest`? – Rob Starling Dec 19 '13 at 18:19
  • 5
    It might not compile if you pull both into scope somewhere else, but even if you choose the wrong one explicitly it should resolve to the same configuration space internally as both configs bind to "it" and I think that is what actually matters. (You can always rename it to MyIntegrationTest if you like.) – Caoilte Dec 19 '13 at 20:00
19

If you want to share code from Test configuration, it's probably better to create a custom test configuration from Test. See Custom test configuration.

Your project/Build.scala becomes:

import sbt._
import Keys._

object MyBuild extends Build {
  lazy val FunTest = config("fun") extend(Test)

  val scalaTest = "org.scalatest" %% "scalatest" % "2.0" % "test"

  lazy val myProject =
    Project(id = "my-project", base = file("."))
      .configs(FunTest)
      .settings(inConfig(FunTest)(Defaults.testSettings) : _*)
      .settings(
        scalaVersion := "2.10.3",
        libraryDependencies ++= Seq(
          scalaTest
        )
      )
}

Also rename src/it/ to src/fun/. Now fun:test works:

> fun:test
helping.
[info] ItSuite:
[info] My code
[info] - should work
[info] Run completed in 245 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 1 s, completed Dec 17, 2013 8:43:17 AM
Eugene Yokota
  • 94,654
  • 45
  • 215
  • 319
  • @Eugene Yokota Is there away to run only specific TestSuite (test Class) when using such custom configuration? Tried `fun:testOnly *MySpecialSuit` with no luck – 3Gee Nov 22 '16 at 17:32