I’m building a gradle plugin with integration tests that use the GradleRunner (gradle v3.0). I have a problem executing the tests because I need to pass in some user credentials (the test is basically doing a “curl -u username:password http://url.example.com”).
I want to avoid having these credentials in a gradle.properties file and would like to pass them on the command line, but these properties do not get propagated to the GradleRunner.
Yeah, I thought that should work for me but it doesn’t for some strange reason.
Does useTestNG() do something special for you?
Basically my code looks something like this
public class integrationTests {
public final TemporaryFolder testProjectDir = new TemporaryFolder()
@Test
public void listReposTest() {
systemProperty username = System.getProperty("username") // for debugging
systemProperty password = System.getProperty("password") // for debugging
BuildResult result = GradleRunner.create()
.withProjectDir(testProjectDir.root)
.withArguments("listRepos")
.withPluginClasspath()
.build()
result.task(":listRepos").outcome == "SUCCESS"
}
}
groovy.lang.MissingPropertyException: No such property: username for class: integrationTests
If I remove those two getProperty debug lines above so that the GradleRunner executes I still get the same error. My actual task looks basically like this:
* What went wrong:
Execution failed for task ':listRepos'.
> Could not set unknown property 'username' for task ':listRepos' of type com.example.gradle.plugins.tasks.ListReposTask.
Even if that did work, I can’t help but feel that it’s a bit of a questionable approach to use the system properties for passing credentials between different JVMs though…
You have to add systemProperty part inside the test task in build.gradle of your project. UseTestNG is used as my tests are TestNG based. This is not needed for Junits.
16:53 wtf → gradle test -Dusername=foo -Dpassword=bar
FAILURE: Build failed with an exception.
* Where:
Build file 'C:\cygwin64\home\user\workspace\wtf\build.gradle' line: 14
* What went wrong:
A problem occurred evaluating root project 'wtf'.
> Could not get unknown property 'username' for task ':test' of type org.gradle.api.tasks.testing.Test.
Same result when running:
gradle test -DsystemProp.username=foo -DsystemProp.password=bar
If it is relevant at all I’m running Cygwin on windows 7 and Gradle 3.0
This cannot work, you are trying to access a variable that doesn’t exist.
Also, I’d generally go with project properties, because those are more Gradle-idiomatic (can be overwritten in gradle.properties, by environment variables etc.
test {
systemProperty "username", findProperty("username")
systemProperty "password", findProperty("password")
}
Thanks for the correction @st_oehme, but we got a bit distracted from solving my actual problem.
Since the GradleRunner forks a process with a separate JVM and context, it does not have the gradle project properties that I provide on the command line when I run
./gradlew test -Pusername=foo -Ppassword=bar
I have explicitly set up some static gradle project properties in my integration tests but how do I solve this problem for credentials? I cannot hard code a username and password in plain text in the source code.
I thought the system properties should work, but for some reason it hasn’t, but that also doesn’t feel like a safe way to pass credentials. For example I suspect those system properties live outside the lifecycle of the java process and only would disappear on a reboot or when they are overwritten.
My thinking is that the best way to do this is to pass the Gradle project object to my integration test class. Or alternatively, initialise my integration test class to look up the gradle project object which has the variables that I need. Any tips on how to do this?
My suggestion above is the first part of the solution. You then have the system properties in your test class, which then needs to pass them to the GradleRunner.
My familiarity with groovy and gradle is still fairly basic so forgive it I have am incorrect on any of the details.
I am doing exactly what you recommended and it works.
My main concern here is in part 2 where the credentials are passed as system properties into the GradleRunner VM. From my understanding, these credentials will be readable by any java process on the system?
I wondered about the persistence of those variables beyond the life of the GradleRunner VM but my testing showed those variables to be null after the tests finished. I was a bit surprised to see that result but happy nonetheless.
In any event, the concerns with gradle are relatively minor compared to the security issues I need to solve with jenkins.
I wasn’t assuming that your build is running in an untrusted environment.
Usually CI servers are under full control. In an untrusted environment your
concern is very valid. But if it is untrusted, then any access to
credentials is a problem.
There’s no real solution to that other than building in a trusted
environment.