I have 3 test source folders in my project. I have added the following key to build.sbt (version of SBT: 1.2.1):
sourceDirectories in Test := baseDirectory { base =>
Seq(
base / "src/test/common/scala",
base / "src/test/unit/scala",
base / "src/test/functional/scala"
)
}.value
SBT correctly recognized the folders:
sbt test:sourceDirectories
...
[info] Set current project to service (in build file:/myprojectfolder/)
[info] * /myprojectfolder/src/test/common/scala
[info] * /myprojectfolder/src/test/unit/scala
[info] * /myprojectfolder/src/test/functional/scala
but test:compile doesn't produce any test classes in target/scala-2.11/test-classes and in result test task doesn't run any tests.
I'm using ScalaTest 3.0.5 although that doesn't seem relevant.
Any ideas why SBT ignores test scala sources during compilation?
Thank you manuzhang for useful comments. Indeed the following change did the trick:
instead of
sourceDirectories in Test := baseDirectory { base =>
Seq(
base / "src/test/common/scala",
base / "src/test/unit/scala",
base / "src/test/functional/scala"
)
}.value
I used
unmanagedSourceDirectories in Test := baseDirectory { base =>
Seq(
base / "src/test/common/scala",
base / "src/test/unit/scala",
base / "src/test/functional/scala"
)
}.value
Related
This is my build.sbt:
name := "DB-Services"
version := "0.1"
scalaVersion := "2.12.12"
lazy val root = (project in file(".")).enablePlugins(UniversalPlugin,JavaServerAppPackaging)
artifactName := { (_, _, _) => "DB-Services.zip"}
Universal / mappings ++= directory(target.value)
Currently sbt package generates DB-Services.zip inside of target/scala-2.12. However I need this ZIP to be generated inside target folder instead. But the problem is that the mapping I provided above does not work and the ZIP continues to be generated inside target/scala-2.12.
What changes should I do in my build.sbt so that the ZIP is generated in target folder? (I cannot generate the ZIP in any other location due to limitations with our CICD)
(PS: This answer does not work, so please do not mark this as duplicate)
Universal / target := (Compile / target).value
Works for me. How I found this:
There is a useful tool in SBT to dive into settings and tasks: inspect
I ran inspect root/Universal/packageBin (root/Universal/packageBin is how we build an artifact), it returned:
...
[info] Dependencies:
[info] Universal / packageBin / validatePackage
[info] Universal / packageBin / mappings
[info] Universal / packageName
[info] Universal / target
[info] Universal / packageBin / universalArchiveOptions
[info] Universal / topLevelDirectory
...
Universal / target looked interesting, so I ran: inspect Universal / target , it returned:
...
[info] Description:
[info] Main directory for files generated by the build.
...
We can find that Compile / target returns a path to the target directory in a same way (or just a read docs).
Reading the following SBT documentation:
https://www.scala-sbt.org/1.x/docs/Appending-Values.html
And also
https://www.scala-sbt.org/1.x/docs/Classpaths.html
I can get on how to create a test source folder with only utils classes to be consume both by the tests in the same project and in all other projects that depend on it.
I tried the following but got compilation issues:
Test / sourceDirectories := Seq( baseDirectory.value / "testFixtures", baseDirectory.value / "test")
And also the following but this time sbt does not find any tests in the project:
sourceDirectory in Test := baseDirectory.value / "test"
Test / unmanagedSourceDirectories += baseDirectory.value / "testFixtures"
any idea ?
Thanks
How do I make sbt include non-Java sources to published artifact ?
I'm using Kotlin plugin and can't figure out how to force sbt to include .kt file into published source jar. It only includes .java files.
A lot of people online suggest adding following code to sbt script but it doesn't help
mappings in (Compile, packageSrc) ++= {
val base = (sourceManaged in Compile).value
val files = (managedSources in Compile).value
files.map { f => (f, f.relativeTo(base).get.getPath) }
},
I also tried
includeFilter in (Compile, packageSrc) := "*.scala" || "*.java" || "*.kt",
Here is output of some variables in sbt console
sbt:collections> show unmanagedSourceDirectories
[info] * /home/expert/work/sideprojects/unoexperto/extensions-collections/src/main/scala
[info] * /home/expert/work/sideprojects/unoexperto/extensions-collections/src/main/java
[info] * /home/expert/work/sideprojects/unoexperto/extensions-collections/src/main/kotlin
sbt:collections> show unmanagedSources
[info] * /home/expert/work/sideprojects/unoexperto/extensions-collections/src/main/java/com/walkmind/extensions/collections/TestSomething.java
which plugin you use for kotlin?
https://github.com/pfn/kotlin-plugin has the option kotlinSource to configure where the source directory is located.
sbt packageBin compiled kotlin files and include them to output jar.
build.sbt
// define kotlin source directory
kotlinSource in Compile := baseDirectory.value / "src/main/kotlin",
src/main/kotlin/org.test
package org.test
fun main(args: Array<String>) {
println("Hello World!")
}
console
sbt compile
sbt packageBin
target/scala-2.13
jar include MainKt.class
and folder org/test contains MainKt.class too.
would this solve your problem?
I found a workaround for this in my project https://github.com/makiftutuncu/e. I made following: https://github.com/makiftutuncu/e/blob/master/project/Settings.scala#L105
Basically, I added following setting in SBT to properly generate sources artifact:
// Include Kotlin files in sources
packageConfiguration in Compile := {
val old = (packageConfiguration in Compile in packageSrc).value
val newSources = (sourceDirectories in Compile).value.flatMap(_ ** "*.kt" get)
new Package.Configuration(
old.sources ++ newSources.map(f => f -> f.getName),
old.jar,
old.options
)
}
For the documentation artifact, I added Gradle build to my Kotlin module. I set it up as shown here https://github.com/makiftutuncu/e/blob/master/e-kotlin/build.gradle.kts. This way, I make Gradle build generate the Dokka documentation. And finally, added following setting in SBT to run Gradle while building docs:
// Delegate doc generation to Gradle and Dokka
doc in Compile := {
import sys.process._
Process(Seq("./gradlew", "dokkaJavadoc"), baseDirectory.value).!
target.value / "api"
}
I admit, this is a lot of work just to get 2 artifacts but it did the trick for me. 🤷🏻 Hope this helps.
I have a simple SBT project, consisting of some Scala code in src/main/scala and some test code in src/test/scala. I use the sbt-assembly plugin to create a fat jar for deployment onto remote systems. The fat jar includes all the dependencies of the Scala project, including the Scala runtime itself. This all works great.
Now I'm trying to figure out a way I can run the Scala tests against the fat jar. I tried the obvious thing, creating a new config extending the Test config and modifying the dependencyClasspath to be the fat JAR instead of the default value, however this fails because (I assume because) the Scala runtime is included in the fat jar and collides somehow with the already-loaded Scala runtime.
My solution right now works but it has serious drawbacks. I just use Fork.java to invoke Java on the org.scalatest.tools.Runner runner with a classpath set to include the test code and the fat jar and all of the test dependencies. The downside is that none of the SBT test richness works, there's no testQuick, there's not testOnly, and the test failure reporting is on stdout.
My question boils down to this: how does one use SBT's test commands to run tests when those tests are dependent not on their corresponding SBT compile output, but on a fat JAR file which itself includes all the Scala runtimes?
This is what I landed on (for specs2, but can be adapted). This is basically what you said was your Fork solution, but I figured I'd leave this here in case someone wanted to know what that might be. Unfortunately I don't think you can run this "officially" as a SBT test runner. I should also add that you still want Fork.java even though this is Scala, because Fork.scala depends on a runner class that I don't seem to have.
test.sbt (or build.sbt, if you want to put a bunch of stuff there - SBT reads all .sbt files in the root if you want to organize):
// Set up configuration for building a test assembly
Test / assembly / assemblyJarName := s"${name.value}-test-${version.value}.jar"
Test / assembly / assemblyMergeStrategy := (assembly / assemblyMergeStrategy).value
Test / assembly / assemblyOption := (assembly / assemblyOption).value
Test / assembly / assemblyShadeRules := (assembly / assemblyShadeRules).value
Test / assembly / mainClass := Some("org.specs2.runner.files")
Test / test := {
(Test / assembly).value
val assembledFile: String = (Test / assembly / assemblyOutputPath).value.getAbsolutePath
val minimalClasspath: Seq[String] = (Test / assembly / fullClasspath).value
.filter(_.metadata.get(moduleID.key).get.organization.matches("^(org\\.(scala-lang|slf4j)|log4j).*"))
.map(_.data.getAbsolutePath)
val runClass: String = (Test / assembly / mainClass).value.get
val classPath: Seq[String] = Seq(assembledFile) ++ minimalClasspath
val args: Seq[String] = Seq("-cp", classPath.mkString(":"), runClass)
val exitCode = Fork.java((Test / assembly / forkOptions).value, args)
if (exitCode != 0) {
throw new TestsFailedException()
}
}
Test / assembly / test := {}
Change in build.sbt:
lazy val root = (project in file("."))
.settings(/* your original settings are here */)
.settings(inConfig(Test)(baseAssemblySettings): _*) // enable assembling in test
At the SBT prompt I am able to add a external directory (which contains linux dynamic libs) to the current compile & test classpath's using the commands -
> set fullClasspath in Compile += Attributed.blank(file("/inotify_deps"))
> set fullClasspath in Test += Attributed.blank(file("/inotify_deps"))
How can I specify this path in Build.scala itself? I tried -
unmanagedBase <<= baseDirectory { base => base / "/inotify_deps" },
But this does not do the job. How can I modify the fullClasspath variable for both Compile/Test from within Build.scala?