Scala library available in both compile and test configuration - scala

I have a library that I wish to expose in both the unit tests in Scala and the code itself.
In sbt, I added my library dependency with configuration "test" and then it's available for tests but I cannot use it in the code. If I leave the configuration be or add "compile" it's not available to be imported in unit tests.
libraryDependencies ++= Seq(
"org.scalacheck" %% "scalacheck" % "1.14.0",
"org.scalatest" %% "scalatest" % "3.0.6" % "test",
"org.scalactic" %% "scalactic" % "3.0.6" % "test")
The main problem is that I expose an abstract class I want to use all over the place in other code: abstract class UnitSpec extends FlatSpec with Matchers with ScalaCHeckDrivenPropertyChecks and also use in the tests of the library. If I add "test" to ScalaCheck it cannot find it in the main code of the library. If I leave it as is, it cannot from org.scalatestplus.scalacheck.ScalaCheckDrivenPropertyChecks. This used to be OK and work fine with 3.0.5 and GeneratorDrivenProperyChecks but that's been deprecated.
Is there a way to achieve what I want? I tried "test->compile" but that also doesn't do what I had hoped...

You can combine configurations. In order to have a library both in compile and test you just add bot configurations.
// wrong: libraryDependencies += "<organization>" %% "<module>" % "<version>" % "compile->compile" % "test->compile"
The syntax means roughly: project configuration dependsOn(->) configuration of libraryDependency.
Update
You can also add the dependency twice with different configurations.
libraryDependencies += "<organization>" %% "<module>" % "<version>",
libraryDependencies += "<organization>" %% "<module>" % "<version>" % "test"
Update 2
I think the syntax in the first example is not what I meant to provide.
libraryDependencies += "<organization>" %% "<module>" % "<version>" % "compile->compile;test->compile"
At least that is what I use in my libraryDependencies.

So you need a trait from the Scalatest JAR in non-test code. I am not sure why it worked before, but it would make sense to me just to remove % "test" from the scalatest dependency. That will make it available in compile and everything from compile is available in test too.
And for Scalactic I think the main use-case for it as a separate dependency is when you need it in compile but only use Scalatest in test (or don't use it at all). If they are both needed for tests only (or for compile), Scalatest will bring Scalactic with it.
I tried "test->compile" but that also doesn't do what I had hoped...
"test->compile" is the same as "test":
A configuration without a mapping (no "->") is mapped to "default" or "compile". The -> is only needed when mapping to a different configuration than those.

Related

sbt Test scope includes Runtime?

I'm configuring SLF4J within an SBT application and the Test vs Runtime scopes are working differently than I'd expect.
The setup I want:
tests (sbt test): use slf4-simple as the implementation
bundle/production runtime (sbt run): use log4j-slf4j-impl
Relevant build.sbt (sbt 0.13) section:
libraryDependencies += "org.slf4j" % "slf4j-simple" % "1.7.25" % Test,
libraryDependencies += "org.apache.logging.log4j" % "log4j-api" % 2.8.2 % Runtime,
libraryDependencies += "org.apache.logging.log4j" % "log4j-core" % 2.8.2 % Runtime,
libraryDependencies += "org.apache.logging.log4j" % "log4j-slf4j-impl" % 2.8.2 % Runtime
The error I'm getting is that there are two slf4j bindings present, the log4j one and the simple.
I'm wondering how the Runtime dependencies can be excluded from the Test scope, or if this is the wrong approach here.
To distill the question: I want to use a few different jars at runtime vs test that are mutually exclusive. How can this be done in sbt 0.13?
The issue is that Test scope includes Compile and presumably Runtime. So anything you add in Runtime it's also added in Test.
You can try to exclude log4j-slf4j-impl from the Test classpath like this:
fullClasspath.in(Test) := fullClasspath.in(Test).value.filterNot(_.data.getName.contains("log4j-slf4j-impl"))

Play+Scala suite test not found type PlaySpecification

It is my first web app using Play Framework and Scala. I am following this tutorial > https://semaphoreci.com/community/tutorials/how-to-add-integration-tests-to-a-play-framework-application-using-scala and after the app working well, my tests cannot work. When I type sbt test the compiler says cannot find PlaySpecification.
[error] /home/felipe/Documentos/AMC/amc-project/play-scala-library/test/controllers/HomeControllerIntegrationSpec.scala:6: not found: type PlaySpecification
[error] class HomeControllerIntegrationSpec extends PlaySpecification {
These are my dependencies >
libraryDependencies ++= Seq(
jdbc,
cache,
ws,
evolutions,
"com.typesafe.play" %% "anorm" % "2.4.0",
"commons-codec" % "commons-codec" % "1.6",
"org.scalatestplus.play" %% "scalatestplus-play" % "1.5.1" % Test
)
resolvers += "scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"
There are two frameworks for testing in play available, specs2 and scalatest. You only need to use one though, not both. In your case things got a bit mixed up:
PlaySpecification is a trait for testing with specs2. However your dependencies contain only scalatestplus (and hence scalatest transitively) which means you're using scalatest to run your tests. In this case you want to use PlaySpec instead, that's the base class for scalatest suites.
Alternatively you can of course switch to specs2 instead, including it's dependency makes PlaySpecification available. Just add specs2 % Test to your dependencies in this case (and best remove scalatestplus).

Is it possible for a Scala project to list its own dependencies?

In sbt, we define dependencies for a project:
libraryDependencies ++= Seq(
"com.beachape" %% "enumeratum" % "1.3.2",
"org.scalatest" %% "scalatest" % "2.2.4" % "test"
)
Is it possible for the Scala application thus compiled to get access to this data, somehow?
I am making a modular system of Play 2.4 APIs and would like the "umbrella" to be able to list which APIs it's carrying.
I will probably get this done using sbt-buildinfo that I found via this question.
Other suggestions are of course welcome.
A simple solution is checking maven repositories. For example, the link below shows all libraries com.beachape" %% "enumeratum" % "1.3.2" depends on.
http://mvnrepository.com/artifact/com.beachape/enumeratum_2.11/1.3.2

Cannot Resolve Symbol "Scalatest"

I am trying to use scalatest, but Intellij cannot recognize:
import org.scalatest._
Here is my build.sbt file, located in the same directory as my scalatest.jar file.
scalaVersion := "2.11.2"
libraryDependencies += "org.scalatest" % "scalatest_2.11" % "2.2.4" % "test"
Thanks
So you have by convention two source folders:
src/main/scala/...
src/test/scala/...
The first is shown blue, the second green in IntelliJ IDEA. The library dependencies in sbt are associated with either of these, so
"org.foo" % "bar_2.11" % "1.2.3"
Is a main dependency, available to main sources (and also test, because test depends on main). And
"org.foo" % "bar_2.11" % "1.2.3" % "test"
Is a test dependency, only available to test sources. The idea is that these are libraries which are not required for your product, but only to run the unit tests.
In your example, Scala-Test is only available to test sources, so trying to import it from main sources will fail.

How to toggle between project and library dependencies in SBT?

It's easy to declare managed library dependencies in SBT, eg
libraryDependencies ++= Seq(
"org.specs2" %% "specs2" % "1.12.2" % "test" ,
"junit" % "junit" % "4.7" % "test"
)
And while it's not as easy to declare project dependencies in SBT, I can do that too:
object RichMath extends Build {
lazy val myApp = Project("RichMath", file(".")) dependsOn(richUtil)
lazy val richUtil = RootProject(file("../RichUtil"))
}
But in practice, I typically want to change between project mode, where changes are immediately visible in upstream projects, and library mode, where I must publish changes to see them in dependent projects, as code matures.
Early in code-base's life, or whenever I'm wanting to make frequent changes across modules, I don't want the hassle of re-publishing just to see changes upstream. But in stable/mature code, I want to specify exactly what version's I'm depending upon.
It seems like SBT treats the two dependencies as completely different. Is there a more straight-forward way to switch between project- and library- dependencies than rewriting my build definition?
I have a few scenarios for my sbt scripts (tests, publishing, production). I start sbt from script (from bash, you may have other environment) with DO=TESTS sbt for example. This is my dynamic dependencies with regard of environment variable:
if (sys.env.contains("LOCAL_BUILD")) {
Seq[Project.Setting[_]](
unmanagedResourceDirectories in Compile <+= baseDirectory { _ / "src" / "main" / "scala" },
libraryDependencies ++= {
Seq(
"org.digimead" %% "digi-lib-slf4j" % "0.2.1-SNAPSHOT" % "test",
"org.digimead" %% "digi-lib-test" % "0.2.1-SNAPSHOT" % "test",
"org.scalatest" %% "scalatest" % "1.9" % "test"
)
}
)
} else {
Seq[Project.Setting[_]](
libraryDependencies ++= {
Seq(
"org.slf4j" % "slf4j-log4j12" % "1.7.1"
)
}
)
}
As you can see I may have different project settings with single .sbt definition controlled by one environment variable. The environment variable affect all project/subproject bunch.
It is true that the two types of dependencies are treated rather differently and it would be nice if they were not. The main obstacle is that sbt needs to know about all external projects before settings are loaded (for various reasons).
For now, the easiest solution is probably an environment variable or system property as described in another answer. Going forward, the following is very close to being possible in sbt, but still needs some more work:
Declare a dependency as usual
libraryDependencies += "org.example" % "rich-util" % "0.1"
Add the source dependency from the command line, overriding the normal dependency automatically in the process
$ sbt
> projects add ../RichUtil
The convention-based approach described in Setting up sbt environment to hack on multiple libraries at once is a special case and would be enabled by this working as well.