I've found the sbt-groovy plugin and it properly compiles both the test and the main sources just fine. However, the definedTests key is always empty; SBT never discovers any groovy tests. I've verified this with a very simple single src/test/groovy/Test.groovy with a single method annotated @Test which should be picked up by the junit-interface.

I think the root of the issue is that the sbt-groovy plugin needs to define the task "definedTests" in its own plugin source code. This task provides a Seq[TestDefinition].

Looking at how SBT itself populates the sequence reveals it uses additional output from the scala compiler (which also happens to compile java files, so it works out of the box for java) in an Analysis class which is populated by output from the IncrementalCompiler

I've fiddled around with the taskdef, but I'm not sure I'm even on the right path. Documentation on this stuff is pretty sparse, or heavily connected to the IncrementalCompiler.

What code do I need in sbt-groovy to produce a Seq[TestDefinition] that satisfies SBT so that I can run tests (picked up by the junit-interface) that are written in Groovy?


The test detection code is in Tests.discover, which you might be interested in. It seems like all you need is the list of methods with annotations and list of subclasses. If you have some way of finding them out, you probably could mimic what's going on in the code.

The discovery code, as you mentioned, relies on the the Analysis datatype, which is the inner gut of the incremental compiler. You might be able to take advantage of the fact that it is sbt (not Scala or Java compiler) that is responsible for incremental compilation. For Java compilation, AnalyzingJavaCompiler.compile calls the compiler and then does the analysis.

In theory, you could define an AnalyzingGroovyCompiler that uses the same mechanism as the one used for the Java compilation. This is not exactly a walk in the park since some of the parts are hidden behind private[sbt]. Long story short, I put together a hacky proof-of-concept that wrangles the incremental compiler into generating Analysis for Groovy code, and was able to detect a test.

I've only tested with one simple use case

import org.junit.Test
import org.junit.Assert

class Foo {
  public void foo() {
    Assert.assertEquals(1, 2)

Running test from sbt yeilds the following output:

> test
[info] Start Compiling Test Groovy sources : /Users/xxx/sbt-2167-groovy/src/test/groovy 
[error] Test Foo.foo failed: expected:<1> but was:<2>, took 0.062 sec
[error] Failed: Total 1, Failed 1, Errors 0, Passed 0
[error] Failed tests:
[error]         Foo
[error] (test:test) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 1 s, completed Aug 23, 2015 5:05:01 AM

It might not work with future versions of sbt. Caveat emptor.


Your Answer

