Accessing build.graddle information from a .java file?

So, let me preface by saying my understanding of gradle is near to non-existent.

I’m running unit tests and I was trying to access some information from my gradle file.

I.e: I have version ‘1.0’ and I want to run a test that verifies the version of my unit test tool to the application. However, I have no idea on how to retrieve that specific thing. I don’t need straight up code but just a pointer in the right direction seeing as I’m completely lost as the moment.

1 Like
  1. generate a property file in a gradle task
  2. wire the task into the DAG before the test task
  3. add the generated folder to the testRuntime classpath
  4. lookup the property file from the classpath in your tests

See here where I dynamically create files in the $buildDir/testkit folder which is added to the testRuntime classpath

2 Likes

Another option is to set the systemProperties of the test task. I dislike this approach because it makes it more difficult to run the test via eclipse/junit since either gradle needs to run the test or you need to set the system property in the junit run target.

With the classpath / property file based approach I can run in eclipse using right click, run as junit test (after an initial gradle build creates the file)

Note: You can right click, run as gradle test for either solution. I just prefer the junit runner (quicker, prettier output)

Mhm, the thing I was wondering is that, in the event that I dynamically create the file, there’s the issue of pointing to it no? (I may be completely wrong here ) I was seeing it this way: I have a test in src/test/java/tests package. Now, if in that tests package I have a file test1.java with the following declaration:

versionOfThisApp = “path to dynamically created file”

Doesn’t this create a compilation problem? Because the file won’t exist at compile time but only at run time no?

In your test just use

InputStream in = getClass().getClassLoader().getResourceAsStream("generated-file.properties");
Properties props = new Properties();
props.load(in);
String version = props.get("version") 

There’s no compilation issue… The filename is a string?

Ah, I’ll try it out then. I was thinking of pointing to a static variable that’s why. using file IO makes much more sense now. Thank you!

That’s also an option. You could generate a .java file and add the folder to the test sources

sourceSets.test.java {
   srcDir "$buildDir/generated" 
} 

Your generation task would need to be wired into the DAG before the “compileTestJava” task

Mhm, thing is I’ve tried ( i think) by doing this way ( an answer you gave in the past)

   task generateSources {
outputDir = file("$buildDir/version")
outputs.dir outputDir
doFirst {
    def srcFile = new File(outputDir, "com/foo/Version.java")
    srcFile.parentFile.mkdirs()
    srcFile.write("""
    package com.foo;
                   public class Version {
                 public static String getVersion() { return "$project.version"; }
                }
           """)
      }
}
compileJava.dependsOn generateSources
compileJava.source generateSources.outputs.files, sourceSets.main.java

Of course I tried this changing the paths and all that
And, I get a bunch of errors because IntelliJ 1)cannot resolve outputs ( or inputs) and the new File call gives me an “Constructor call is ambiguous”

I’ve also tried using

processResources { expand ( project.version) }

into a version.properties file which contained

   version=%APP_VERSION_TOKEN%

but all that returns is %APP_VERSION_TOKEN%.
Could that be because of my file structure where I don’t have a main ( i only have src/test/java/tests package ) - though I doubt that affects the tests at all
Unfortunately I’m taking over this tool for someone but my understanding of gradle is near to none, so I’m going by searching even though this is more advance than beginner tasks.

You’ll want to add the sourceDir to the sourceSets model rather than tweaking the compileJava task directly.

Do this

build.gradle

apply plugin: 'java' 
repositories {
   ... 
} 
dependencies {
   testCompile 'junit:junit:4.12'
}
task generateTestSources {
	inputs.property "version", project.version
	outputs.dir "$buildDir/generated"
	doFirst {
		def versionFile = file("$buildDir/generated/foo/Version.java")
		versionFile.parentFile.mkdirs()
		versionFile.text = 
"""
package foo;

public class Version {
	public static String getVersion() {
		return "$project.version";
	}
}
"""
	}
}

compileTestJava.dependsOn generateTestSources

sourceSets.test.java {
	srcDir "$buildDir/generated"
}

src/test/java/foo/VersionTest.java

package foo;

import org.junit.*;

public class VersionTest {
	@Test
	public void testVersion() {
		Assert.assertEquals("unspecified", Version.getVersion());
	}
}
2 Likes

So… what’s happening here ( at the same time ill try to take the opportunity of understanding)

We created a task in gradle and

Because right now, I have a VerstionTest in package tests ( src/test/java/tests/VersionTest.java)

However, if I do Version.getVersion() I get a “cannot resolve symbol” on version. I tried to run it through gradle ( ./gradlew test --tests VersionTest.java ) - or any other extension for that matter.

I really don’t know what else to do / add. I don’t know if the rest of my build.gradle file may be interfering with the task generateTestSources

EDIT: I tried doing tests.Version.getVersion() and it solved my problem but it returns an unspecified… weird.

EDIT 2: it worked, just when debugging the actual function is written like this:

    package tests;

public class Version {
	public static String getVersion() {
		return "unspecified";
	}
}

so I’m guessing in the build.gradle I’m not relaying the variable correctly or something

It worked, I created a gradle.properties file and put my version in there and relayed it in my build.gradle.

Doing version ‘4.2’ directly in build.gradle didn’t seem to work. Thank you so much for keeping your patience Lance, time for me to go get some tutorial done on gradle haha

I feel I’ve given enough food for thought including two working examples. Please grok it

1 Like