testSrcDirs property in Test task - src/test/groovy not included

I noticed that when the groovy plugin is enabled, the test task’s testSrcDirs has only java classes listed. Here is the smallest build script to reproduce:

apply plugin: 'groovy'
println test.testSrcDirs

and the output:

$ gradle
[/home/wujek/projects/gt/src/test/java]

It also happens in my real project, which actually has no single file in src/test/java, but rather all tests are in src/test/groovy.

  1. What is this setting used for? 2. Is it a Gradle / Groovy plugin bug, or am I supposed to configure the dirs myself? 3. If configure myself, how? I found:
testSrcDirs = (sourceSets.test.java.srcDirs + sourceSets.test.groovy.srcDirs).asList()

which arguably is pretty complex. Any better options? (Actually, above I could probably just use += sourceSets.test.groovy.srcDirs, but in reality I have a completely new test task where I need to overwrite the default setting completely, not append to it).

wujek

Only case where ‘test.testSrcDirs’ is currently used is for TestNG tests with old-school Javadoc annotations. As such it’s mostly a relic of the past.

‘relict of the past’ sounds rather strange for a project that has just gotten 1.0, but Ok.

The src dirs turn out in the test task inputs, however, as my output says, but changing a groovy file in a directory that is not listed is detected as the compiled classes changed, which is good.

So I guess from my tests and your statement, that I can just simply ignore this fact? Is there any cleanup pending for such ‘relicts’, or would you like me to file a ticket for it?

The property is a relic of the past because it won’t be needed for new code. We have to keep it for backwards compatibility and to support legacy code. You can ignore it if you aren’t using TestNG tests with Javadoc annotations. Feel free to send a pull request for the Groovy plugin.

Sorry, I don’t have a github account (yet?). But below is a patch, which after applying, causes the test case from above print the correct srcDirs: $ /home/wujek/projects/gradle-src/build/distributions/gradle-1.1-rc-1-20120715191014+0200/bin/gradle [/home/wujek/projects/gt/src/test/java, /home/wujek/projects/gt/src/test/groovy]

The patch is very naive, as it just takes the conventionMapping and maps testSrcDirs to the appropriate directories. It should read the already present setting and just add it it (but I guess it is some kind of a callable?). Also, what happens when all Java, Groovy and Scala plugins are applied? If they decorate / add to the present source sets, there seems to be a circularity there. But maybe it is a non-issue? I know too little about the internals to fix this quickly.

The patch:

diff --git a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/GroovyPlugin.java b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/GroovyPlugin.java
index a2fbe8f..5022555 100644
--- a/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/GroovyPlugin.java
+++ b/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/GroovyPlugin.java
@@ -16,12 +16,19 @@
    package org.gradle.api.plugins;
   +import org.gradle.api.Action;
 import org.gradle.api.Plugin;
 import org.gradle.api.Project;
 import org.gradle.api.internal.plugins.DslObject;
 import org.gradle.api.tasks.GroovySourceSet;
 import org.gradle.api.tasks.SourceSet;
 import org.gradle.api.tasks.javadoc.Groovydoc;
+import org.gradle.api.tasks.testing.Test;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.concurrent.Callable;
    /**
  * <p>A {@link Plugin} which extends the {@link JavaPlugin} to provide support for compiling and documenting Groovy
@@ -37,6 +44,7 @@ public class GroovyPlugin implements Plugin<Project> {
         project.getPlugins().apply(JavaPlugin.class);
         configureConfigurations(project);
         configureGroovydoc(project);
+
      configureTest(project);
     }
        private void configureConfigurations(Project project) {
@@ -57,4 +65,24 @@ public class GroovyPlugin implements Plugin<Project> {
         GroovySourceSet groovySourceSet = new DslObject(sourceSet).getConvention().getPlugin(GroovySourceSet.class);
         groovyDoc.setSource(groovySourceSet.getGroovy());
     }
+
+
  private void configureTest(final Project project) {
+
      project.getTasks().withType(Test.class, new Action<Test>() {
+
          public void execute(Test test) {
+
              test.getConventionMapping().map("testSrcDirs", new Callable<Object>() {
+
                  public Object call() throws Exception {
+
                      JavaPluginConvention javaConvention = project.getConvention().getPlugin(JavaPluginConvention.class);
+
                      SourceSet sourceSet = javaConvention.getSourceSets().getByName(SourceSet.TEST_SOURCE_SET_NAME);
+
                      GroovySourceSet groovySourceSet = new DslObject(sourceSet).getConvention().getPlugin(GroovySourceSet.class);
+
                      Set<File> javaSrc = sourceSet.getJava().getSrcDirs();
+
                      Set<File> groovySrc = groovySourceSet.getGroovy().getSrcDirs();
+
                      ArrayList<File> allSrc = new ArrayList<File>(javaSrc.size() + groovySrc.size());
+
                      allSrc.addAll(javaSrc);
+
                      allSrc.addAll(groovySrc);
+
                      return allSrc;
+
                  }
+
              });
+
          }
+
      });
+
  }
 }

wujek

Actually, after a good night’s sleep, I think there is no problem with circular scrDirs when using multiple plugins that add their own src dirs (Groovy, Scala) - these plugins are applied in the order they are defined in the build file, right? So, both of these plugins just have to read what is already set, and complement it with their own additional libs, and it all should work.