Reputation: 3039
I am using Play 2.3.4, IDEA 13.1.5 Ultimate and am trying to write some JUnit tests in code structured with activator new experimentApp play-java
.
Besides the Root module (which is pretty much unchanged to the original template), there is a Child module to it with standard directory structure so:
src/main/java
-> contains 1 class called org.net.ClassOne
src/main/test
-> contains 1 test class called org.net.ClassOneTest
Both of these classes are in Child module.
Code for the classes is trivial:
ClassOne:
public class ClassOne {
public String test() { return "Smoke test"; } }
ClassOneTest:
public class ClassOneTest {
@Test public void simpleCheck() { int a = 1 + 1; assertThat(a).isEqualTo(2); } @Test public void smokeTest() { ClassOne smoke = new ClassOne(); assertThat(smoke.test()).isEqualTo("Smoke test"); } }
My Root build.sbt
config is this:
.....
lazy val Root = (project in file("."))
.enablePlugins(PlayJava)
.aggregate(child)
.dependsOn(child)
lazy val child = project in file("Child")
.....
Since the Root module is unchanged from the play-intro-java
template, it contains its original classes directly under test/
directory and on running activator clean compile test
both of the classes get run regularly.
However, the JUnit test in the Child module (the class quoted above) in Child module are completely ignored on activator clean compile test
. If I try to run ClassOneTest
from IDEA, it runs without errors, which tells me classpath is formed correctly however I am missing some activator/sbt configuration part.
Just to make things totally obvious, running activator clean compile test
on:
[info] Done updating.
[info] Compiling 4 Scala sources and 2 Java sources to R:\intellij-projects\Root\target\scala-2.11\classes...
[info] Compiling 2 Java sources to R:\intellij-projects\Root\target\scala-2.11\test-classes...
[info] Passed: Total 3, Failed 0, Errors 0, Passed 3 [success] Total time: 15 s, completed Oct 7, 2014 10:22:26 AM
[info] Done updating.
[info] Compiling 1 Java source to R:\intellij-projects\Root\Child\target\scala-2.10\classes...
[success] Total time: 2 s, completed Oct 7, 2014 10:47:11 AM
[info] Compiling 1 Java source to R:\intellij-projects\Root\Child\target\scala-2.10\test-classes...
[success] Total time: 1 s, completed Oct 7, 2014 10:47:12 AM
So the questions are:
activator
failing to notice JUnit tests in Child module only? It runs the tests in Root module fine and I would expect activator
to pick all tests up when run in Root module, let alone Child module,activator
disregarding the directive scalaVersion in ThisBuild := "2.11.1"
placed in Root build.sbt
? It is only after I place this expression in Child build.sbt
, the classes are compiled in expected directory, i.e. ...\scala-2.11\...
I have read the other SO questions and:
clean
doesn't fix the issue@RunWith(JUnit.class)
is not placed in my testsEDIT: As I suspected, after amending the Root build.sbt
with
lazy val Child = (project in file("Child")).enablePlugins(PlayJava)
and placing the ClassOneTest
directly under test/
and ClassOne
under app/
, all the tests are correctly executed when running from Root, so
activator clean compile test
...
[info] Done updating.
[info] Compiling 4 Scala sources and 2 Java sources to R:\intellij-projects\Root\target\scala-2.11\classes...
[success] Total time: 10 s, completed Oct 7, 2014 11:20:40 AM
[info] Compiling 1 Java source to R:\intellij-projects\Root\Child\target\scala-2.11\test-classes...
[info] Compiling 2 Java sources to R:\intellij-projects\Root\target\scala-2.11\test-classes...
[info] Passed: Total 2, Failed 0, Errors 0, Passed 2
[info] Passed: Total 3, Failed 0, Errors 0, Passed 3
[success] Total time: 7 s, completed Oct 7, 2014 11:20:47 AM
Interestingly, running the activator clean compile test
from Child doesn't invoke any tests(?). Surely, there must be a way to tell Play where the test classes are at?
Upvotes: 2
Views: 1468
Reputation: 11284
First off, you should understand a little more sbt, so I'd recommend reading through some of the introductory sbt docs (activator is just a UI for sbt).
Play is called a framework instead of a library because it is a fundamental approach to how you develop your app. One effect of that is that it changes the default source organization from src/main/java|scala
to just app
. If you enable Play on your root project and you aggregate all sub-projects, this effect will be project-wide. Edit: This is incorrect, your subproject does not use Play if you don't enable the plug-in on it explicitly.
So if you want your subproject not to be a Play project, your root project shouldn't be a Play project either.
Personally, when I'm using sub-projects, I'm not using the root project as something runnable, but only as a container for global configurations and settings. Using the root project as your main app is perfectly fine, though.
Update:
After some testing, this must have to do with JUnit and sbt (Play already handles this for you). I've setup a Scala project with one Play-subproject and one normal sub-project, and everything works fine. When I run sbt test
on the root project, all tests are executed.
dependsOn
is only required when one project depends on the code of another one.
Upvotes: 1
Reputation: 3039
I have been able to do what I want - which is to have separate project settings in Root project (default Play settings as this will be the web-app using Child jars) and Child project(s) (which will be just jars contributing logic to web-app).
The solution is to amend Root and Child build.sbt
s in this way:
Root
lazy val root = (project in file("."))
.enablePlugins(PlayJava)
.aggregate(child)
.dependsOn(child)
lazy val child = (project in file("Child")).enablePlugins(PlayJava)
Child
// compile-scoped directories
javaSource in Compile <<= baseDirectory / "src/main/java"
resourceDirectory in Compile <<= baseDirectory / "src/main/resources"
scalaSource in Compile <<= baseDirectory / "src/main/scala"
// test-scoped directories
javaSource in Test <<= baseDirectory / "src/test/java"
resourceDirectory in Test <<= baseDirectory / "src/test/resources"
scalaSource in Test <<= baseDirectory / "src/test/scala"
produces
[info] Done updating.
[info] Compiling 4 Scala sources and 2 Java sources to R:\intellij-projects\esi-load\target\scala-2.11\classes...
[info] Passed: Total 2, Failed 0, Errors 0, Passed 2
[info] Compiling 2 Java sources to R:\intellij-projects\esi-load\target\scala-2.11\test-classes...
[info] Passed: Total 3, Failed 0, Errors 0, Passed 3
[success] Total time: 17 s, completed Oct 7, 2014 12:58:47 PM
There were several key insights here:
activator
seems to be oblivious to projects that don't have enablePlugins(PlayJava)
called on project construction
once that is realized, a chance discovery lead me to this Play 2.0.4 page listing all the default Play settings - for the reasons I can't understand, these settings have been deleted from Play 2.3.4 page. It was then trivial to override those settings in Child build.sbt
Point 2) tell me that is either an oversight or there is something fundamentally wrong with my approach so if there is a better way to do this, I would be very interested to hear it. Until that time, I am (reluctantly) accepting my own answer.
Upvotes: 1