How to change the location of twirl templates for integration tests? - scala

I'm trying to use twirl as part of my integration tests.
My integration tests have an HTTP simplicator that mimics a real world service. To implement this simplicator in the tests, I'm using spray-can embedded HTTP server which needs to spit out responses based on twirl templates.
My tests are located at /src/it/scala so naturally I want to place these twirl templates inside /src/it/twirl. This doesn't work since the twirl compiler ignores this directory.
If I place the twirl templates in /src/main/twirl, everything works fine - but I'm trying to avoid this because I don't want these templates to clutter the production package (the templates only come into play in the tests so they should only compile inside when the tests are run).
How can I tell the twirl compiler to look for templates in the new directory?

You should really be using sourceDirectory in twirlCompile that by default is set to:
sourceDirectory in twirlCompile <<= (sourceDirectory in Compile) / "twirl"
Redefine the sourceDirectory setting for the twirlCompile task for the IntegrationTest config. The following should work (it's yet to be verified).
sourceDirectory in twirlCompile in IntegrationTest := (sourceDirectory in IntegrationTest).value / "twirl"

Related

How IntelliJ (or sbt-structure) identifies test sources?

Background
I've created template-scala-project which, among other amenities, defines configurations FunctionalTest and AcceptanceTest (in addition to IntegrationTest, which is provided by SBT).
This way, the relevant bits of the directory structure are:
src/main/scala - compile sources - Compile
src/test/scala - test sources - Test
src/it/scala - it sources - IntegrationTest
src/ft/scala - ft sources - FunctionalTest
src/at/scala - at sources - AcceptanceTest
Behavior in SBT
I can run only functional tests, for example, like this:
ft:test
Everything works as I've planned. I can even share test sources to it sources, or ft sources, or at sources... which is a common practical requirement.
Behaviour in IntelliJ
IntelliJ recognizes that src/test/scala and src/it/scala are test sources. IntelliJ does not have any distinction between them, I mean: no distinction between test sources and integration test sources, ... but it's OK. All I need is that src/it/scala is recognized as test sources. And it works as that.
However, IntelliJ does not recognize src/ft/scala as test sources; IntelliJ does not recognize src/at/scala as test sources.
I have inspected the XML file produced by sbt-structure but I was unable to understand the pattern or logic behind it. However (and apparently!) src/ft/scala and src/at/scala should appear under <configuration id="test"> in order to be eligible for being considered as test sources.
Question
In order to test my hypothesis above, I would like to force src/ft/scala to appear under <configuration id="test">, employing "something" in the build.sbt file. How could I accomplish that?
If you want a directory in IntelliJ to be considered a Test Source directory, you can configure it as such by simply right clicking it and selecting Mark Directory As > Test Sources Root
That changes your project structure configuration to let IntelliJ know that tests reside there. The same is true of your resources if those need to be marked appropriately.
With THAT said, I suppose I'm not 100% sure if IntelliJ's use of sbt will recognize that and run them appropriately, but I would expect it to.
After some experimentation, I apparently found something which works well enough. I cannot claim that I've found a solution, but at least it seems to work as I would expect: IntelliJ recognizes FunctionalTest (test) sources and AcceptanceTest (test) sources, the same way it recognizes Test sources and IntegrationTest sources.
Answer:
Create a configuration which extends Runtime and Test. Doing this way, src/ft/scala appears under <configuration id="test">, as the XML file is produced by sbt-structure. See the example below for configuration FunctionalTest:
lazy val FunctionalTest = Configuration.of("FunctionalTest", "ft") extend (Runtime, Test)
As a bonus, I show below some other settings which I find useful to be associated to configuration FunctionalTest:
lazy val forkSettings: Seq[Setting[_]] =
Seq(
fork in ThisScope := false,
parallelExecution in ThisScope := false,
)
lazy val ftSettings: Seq[Setting[_]] =
inConfig(FunctionalTest)(Defaults.testSettings ++ forkSettings ++
Seq(
unmanagedSourceDirectories in FunctionalTest ++= (sourceDirectories in Test).value,
unmanagedResourceDirectories in FunctionalTest ++= (resourceDirectories in Test).value,
))
I also did something similar for configuration AcceptanceTest.
You can find a project which exercises such kind of configurations at:
http://github.com/frgomes/template-scala-project

SBT src_managed not availabe for compilation

In my project I have a special SBT plugin to generate some configuration specific settings (like sbt-buildinfo). A special task generates a Scala class and stores it in 'src_managed' folder.
The problem is, that after this file is successfully generated, the following 'compile' can't find this class and I get compilation error.
I have several configurations defined with:
compile in conf <<= (compile in conf).dependsOn(mytask)
I call this plugin like so:
;clean;proj/myconf:compile
You should setup special setting for code generator:
sourceGenerators in Compile <+= (myCodeGeneratorTask in Compile)
SBT generate code using project defined generator

Real SBT Classpath at Runtime

I have some test cases that need to look at the classpath to extract the paths of some files/directories in there. This works fine in the IDE.
The problem is that, when running SBT test, Properties.javaClassPath gives me /usr/share/sbt-launcher-packaging/bin/sbt-launch.jar.
The classpath is fine when I run show test:dependency-classpath. Is there a way to obtain that information from inside the running Scala/Java program? Or is there a way to toss it into a system property or environment variable?
By default the tests are run inside of the SBT process, so the classpath will look like it did when you started sbt (I guess sbt does some trixery to dynamicly load the classes for the tests, not sure). One way to do what you want is to run your tests in a forked jvm, that way sbt will start a new jvm to run the test suite and that should have the expected class path:
fork in Test := true
I have been working on understanding how the EmbeddedCassandra works in the spark-cassandra-connector project which uses the classpath to start up and control a Cassandra instance. Here is a line from their configuration that gets the correct classpath.
(compile in IntegrationTest) <<= (compile in Test, compile in IntegrationTest) map { (_, c) => c }
The entire source can be found here: https://github.com/datastax/spark-cassandra-connector/blob/master/project/Settings.scala
Information on the <<= operator can be found here: http://www.scala-sbt.org/0.12.2/docs/Getting-Started/More-About-Settings.html#computing-a-value-based-on-other-keys-values. I'm aware that this is not the current version of sbt, but the definition still holds.

scalajs: multiple apps in one project?

If I understood scalajs docs correctly it allows only one javascript generation per project.
Is there a way to avoid this limitation?
Currently I created scalajs sub project for Play framework. In this sub project I planned to create all scalajs apps for the service I am working on. Now I found this limitation and it's really confusing and annoying, because the only two solutions I can think of are:
create one "mega-script" which isn't acceptable for me
for every scalajs app create separate sub projects
They both are really not acceptable for a big project.
Every scalajs in it's own subproject and manage everything via SBT MutliProject
Here is somewhat complex example of play project, that has 6+ subprojects that compiles to one single file. scala-js-binding
Check the Build.scala
lazy val preview = (project in file(".")).enablePlugins(PlayScala) settings(previewSettings: _*) dependsOn shared dependsOn bindingPlay aggregate frontend
//aggregate scalaJs
lazy val frontend = Project(
id = "frontend",
base = file("frontend") ) dependsOn shared dependsOn binding
...
scalajsOutputDir := baseDirectory.value / "public" / "javascripts" / "scalajs",
//fastOptJs - not optimized (3Mb)
compile in Compile <<= (compile in Compile) dependsOn (fastOptJS in (frontend, Compile)),
//fullOptJS - fully optimized (330k)
dist <<= dist dependsOn (fullOptJS in (frontend, Compile)),
Scala.js is indeed designed to generate one JavaScript output per project. There is virtually no way to change this.
However, this is not a restriction of Scala.js. Scala/Java themselves behave the same way: you cannot generate two .jars from a single sbt project for a Scala/Java application. So I do not see why Scala.js should behave any differently.
Use multiple projects in your sbt build for this, as suggested by #user3430609.

How do I use shared configurations across SBT (Play) multi-projects?

I have several SBT 0.13 / Play 2.2 projects (websites). They are all multi-module as they share some common functionality. This makes their project configuration files both complex and almost identical, but not quite.
I would like to be able to share as much as possible of these configuration files across the projects (frequent play updates makes keeping 5+ websites up to date a royal pain, not to mention all the almost-identical-but-evolving dependency lists across the projects).
build.properties and plugins.sbt are identical across projects and can be overwritten by a simple script. Great.
Build.scala is trickier - I would like to introduce a shared base class like so:
abstract class MyBuildBase extends Build { ... }
that in Build.scala do:
object ApplicationBuild extends MyBuildBuild { ... }
In order for this to make any sense at all, MyBuildBase.scala needs to be shared across projects. This can be done with svn:external, which operates on directories. Which means I need to somehow make this shared directory accessible when Build.scala is compiled (otherwise sbt complains loudly).
Reading http://www.scala-sbt.org/0.13.0/docs/Detailed-Topics/Classpaths.html and http://www.scala-sbt.org/0.13.0/docs/Getting-Started/Full-Def.html it seems like this should be possible.
However, it is exceptionally unclear to me what to actually put in the project/project/Build.scala file to actually achieve this - I can't find an example of "an sbt build file that's intended to build an sbt build file and include some extra source files in the build".
Any suggestions?
What you probably want to do is create a plugin, or shared library.
You can make an sbt project with a build like follows:
build.sbt
sbtPlugin := true
organization := "you"
name := "common-build"
version := "1.0"
Then create in src/main/scala your abstract class "MyBuildBase". Release this project as an sbt plugin.
Then in your other projects, you can use this as a library/plugin. In project/plugins.sbt add:
addSbtPlugin("you" % "common-build" % "1.0")
And this will resolve your common build library when building your build.
If you need more information, look up more about sbt plugins and ignore the part about making something that extends a Plugin. Plugins are just libraries versioned with sbt's version number and your own. You should be able to put whatever code you want in there to share between builds.
Note: in 2016, Build.scala is deprecated for Build.sbt.
Here is the new (Dec. 2016) multi-module with App Scala sbt template by Michael Lewis.
Usage
sbt new lewismj/sbt-template.g8
You can then run:
sbt compile
sbt publish-local
sbt assembly
It is based on Scala SBT template (Library)
This giter8 template will write SBT build files for a Scala library.