Java: How to add Environment Variables to a JUnit Tests in Gradle - gradle

I've managed to get the test task to run my unit tests, but they fail because env properties I am using are not set, eg: String base=System.getenv("TESTNG_BASE_PATH");
So, I've done something like:
tasks.withType(Test) {
systemProperty 'TESTNG_BASE_PATH','long\\path\\to\env\var\value'
}
But I still get the same exception from my code that the file is not found, so its obviously not the right way of doing this.
So how to do this, please?

If you are getting via System.getenv(...) you'll need to set an environment variable. I've also included a command line flag for switching on/off standard streams
tasks.withType(Test) {
environment 'TESTNG_BASE_PATH','long\\path\\to\env\var\value'
testLogging.showStandardStreams = Boolean.parseBoolean(findProperty('showStandardStreams'))
}
To run you could do
./gradlew check -PshowStandardStreams=true

Related

Gradle: get task command line arguments inside the task

I'm running my tests with gradle using the command line:
./gradlew testManager:uiTest -PignoreTestFailures=true" +
"-DCHROMEDRIVER_VERSION=${env.CHROMEDRIVER_VERSION}" +
"-DBASE_URL=${params.BASE_URL}"
I need to propagate passed properties (e.g. BASE_URL) to the JMV with tests from the gradle task.
I know I could do the following inside the task:
systemProperties System.properties
But I'd like to avoid passing the whole set, as it overrides some other required values in tests.
So the question is: is there a way to get the only properties passed via -D command line parameter, inside the gradle task?
Found this pretty easy way:
task uiTest(type: Test) {
doFirst {
/* Propagate only command line start properties (-D) to the tests */
project.gradle.startParameter.systemPropertiesArgs.entrySet().collect() {
systemProperty it.key, it.value
}
}
}
So in a case of
./gradlew testManager:uiTest -PincludeTests=saveReleaseState/** -DBASE_URL=foobar
The tests receive only BASE_URL=foobar

How to avoid copy'n'paste in gradle?

I have a build.gradle file for my spring-boot application. I have a few environment details I wish to change for some of the gradle tasks. Specifically for the gradle tasks 'test', 'runSmokeTest' and 'bootRun'. In all the tasks I have to make the same calls, so I would prefer if I could extract a method out of that. Or a task. But whenever I do that, suddendly gradle no longer finds the functions that I require.
These are the calls I need to make:
systemProperties System.properties
systemProperty "spring.cloud.config.failFast", "false"
if (project.hasProperty("TEAM_ENCRYPT_KEY"))
environment "ENCRYPT_KEY", "$TEAM_ENCRYPT_KEY"
The code works perfectly fine when included directly in the bootRun task, the test task and the runSmokeTest task via copy'n'paste. I would prefer not to duplicate the code. I tried the following approach to extract them from the bootRun task, but Gradle keeps complaining that he does not find the functions systemProperty and environment. Similarly if I use the Intellij integrated feature 'extract Method':
task specialConfiguration() {
systemProperties System.properties
systemProperty "spring.cloud.config.failFast", "false"
if (project.hasProperty("TEAM_ENCRYPT_KEY"))
environment "ENCRYPT_KEY", "$TEAM_ENCRYPT_KEY"
}
bootRun {
dependsOn 'specialConfiguration'
}
How can I extract this short piece of code from the 3 tasks to avoid duplicate code?
Gradle keeps complaining that he does not find the functions systemProperty and environment
This is a prime example where the Kotlin DSL would shine. You would know exactly what methods/properties are available at any given time because it's a strongly type language unlike Groovy.
With that said, when you do the following:
task specialConfiguration() {
systemProperties System.properties
systemProperty "spring.cloud.config.failFast", "false"
if (project.hasProperty("TEAM_ENCRYPT_KEY"))
environment "ENCRYPT_KEY", "$TEAM_ENCRYPT_KEY"
}
bootRun {
dependsOn 'specialConfiguration'
}
You are:
Declaring a task named specialConfiguration.
No type was specified so the type is DefaultTask.
Configure bootRun task to depend on specialConfiguration
I think you are assuming that dependsOn is like "configuring" a task when really it's just adding a dependency to the task. See Adding dependencies to a task.
I am assuming that runSmokeTest is of type Test. So tasks test, runSmokeTest, and bootRun all implement the JavaForkOptions interface which is where the systemProperties(..), systemProperty(.., ..) and environment(.., ..) methods come from.
With that said, since you know the three tasks you want to configure, and they all implement JavaForkOptions and in some fashion, you can do (Kotlin DSL):
import org.springframework.boot.gradle.tasks.run.BootRun
// Assuming this is a Test task type
tasks.register("runSmokeTest", Test::class)
// Define a new Action (configuration)
val taskConfig = Action<JavaForkOptions> {
systemProperties(System.getProperties() as Map<String, Any>)
systemProperty("spring.cloud.config.failFast", false)
if (project.hasProperty("TEAM_ENCRYPT_KEY")) {
environment("ENCRYPT_KEY", project.property("TEAM_ENCRYPT_KEY")!!)
}
}
// Configure all three tasks
tasks.named("test", Test::class, taskConfig)
tasks.named("runSmokeTest", Test::class, taskConfig)
tasks.named("bootRun", BootRun::class, taskConfig)
The Groovy version of Francisco Mateo's answer, in case anyone needs that.:
Closure<JavaForkOptions> configAction = {
systemProperties System.properties
systemProperty "spring.cloud.config.failFast", "false"
if (project.hasProperty("MOBTECH_ENCRYPT_KEY"))
it.environment "ENCRYPT_KEY", "$MOBTECH_ENCRYPT_KEY"
}
# Configure the tasks with it
bootRun (configAction)

Build Gradle getProperties before running already made task

I’m trying to use a Java, Serenity-BDD project with gradle version 4.8+, but the application is not pulling the CLI arguments of -Denvironment and -Dservicebranches. I have these properties as blank values in my local.properties file, and they’re not getting assigned when my app runs.
./gradlew --build-cache build -Dwebdriver.remote.url=${SELENIUM_REMOTE_URL} -Denvironment=${ENVIRONMENT} -Dservicebranches=${SERVICE_BRANCHES} -Dtags=${TAGS}
I have a local.properties file with properties that are being successfully dependency injected into the project (through Serenity-Spring). I'm hoping that these CLI arguments will override these values:
servicebranches=
environment=local
But right now, anything specified in the CLI arguments are not being passed into the project. Either through DI, or through explicitly grabbing the environment variables in the build.gradle, which what I've tried hasn't been working.
Here's a few things which I have tried in the build.gradle:
//task integrationTests() {
// doFirst
// {
// def environment = System.getProperty('environment')
// def servicebranches = System.getProperty('servicebranches')
// }
// tasks.build.execute()
//}
//integrationTests.dependsOn(build)
//build.doFirst{
// systemProperties System.properties
// def environment = System.properties['environment']
// environment = environment //This actually flags with 'Silly assignment'
//}
build.doFirst{
def environment = System.getProperty('environment')
def servicebranches = System.getProperty('servicebranches')
}
The latest one seems to still be missing a step, because the program is still working, but the args are still not getting through. I've even tried -Denvironment=potato, and no errors have come up because I do not have a property or properties file named that.
I've also tried using the -P tag instead of -D tag, but that doesn't seem to be working either.
All I’m trying to do is use build.gradle to use System.getProperty(‘environment’) and System.getProperty(‘servicebranches’) before I use the already created ‘build’ task that comes with Serenity. How would I do this? Do I build a whole new task, where I use these getProperties, and then call the build task? Do I have to specify the assignment of these same named variables in the local.properties file?
-D is for system properties in Gradle. Try with -P instead (https://docs.gradle.org/current/userguide/build_environment.html#sec:project_properties)
I know this is a very old question but here's what I did to solve my problem, I got the idea from here: https://github.com/serenity-bdd/serenity-documentation/pull/120/files
Serenity was not pulling the environment from gradle to use EnvironmentSpecificProperties, it kept saying "undefined property for environment 'null" when I removed the default environment. I had to add this to my Gradle file:
test {
systemProperty 'environment', System.properties['environment']
}

How to pass system properties to the tests in gradle in the smart way?

build.gradle
tasks.withType(Test){
systemProperties=System.properties
println systemProperties['param']
}
Now I can either pass parameters in the command line:
gradle test -Dparam=10
or put them in gradle.properties:
systemProp.param=15
Ideally I would like to put the defaults in the gradle.properties, and be able to overwrite them from the command line. Unfortunately if I do that, the gradle.properties has precedence, and -Dparam=10 is ignored.
Could you offer any solutions on that?
https://issues.gradle.org/browse/GRADLE-2122
It works since 2.12 or 2.13 "the smart way" already!
The example above is working, the command line -D option overdrives the defaults in gradle.properties
I am using gradle 2.12 and sharing how I used it:
test {
// support passing -Dsystem.property=value to bootRun task
systemProperties = System.properties
}
I have JUnit tests that I wanted to skip unless a property was used to include such tests. Using JUnit Assume for including the tests conditionally:
//first line of test
assumeThat(Boolean.parseBoolean(System.getProperty("deep.test.run","false"),true)
Doing this with gradle required that the system property provided at the time of running gradle build, shown here,
gradle build -Ddeep.test.run=true
was indeed passed through to the tests.
Hope this helps others trying out this approach for running tests conditionally.

How to pass system property to Gradle task

I'm using Gradle spring-boot plugin and I need to select a spring active profile for the test run.
How do I pass spring.profiles.active system property to the bootRun plugin's task?
What has already failed:
task bootRunLocal {
systemProperty "spring.profiles.active", "local"
System.setProperty("spring.profiles.active", "local")
tasks.bootRun.execute() // I suspect that this task is executed in a separate JVM
}
and some command line magic also fails:
./gradle -Dspring.profiles.active=local bootRun
Could someone kindly help me solve my troubles?
Update from the answers and comments:
I'm able to set the systemProperty and pass it to the spring container by doing :
run {
systemProperty "spring.profiles.active", "local"
}
However, when I do this, the local profile is being set for both bootRun task and bootRunLocal task. I need a way to set this property for bootRunLocal task and call booRun task from bootRunLocal.
That might sound very simple, but I come with peace from the structured world of Maven.
I know I'm late here... but I recently faced this exact issue. I was trying to launch bootRun with spring.profiles.active and spring.config.location set as system properties on the command line.
So, to get your command line "magic" to work, simply add this to your build.gradle
bootRun {
systemProperties System.properties
}
Then running from the command line...
gradle -Dspring.profiles.active=local bootRun
Will set local as the active profile, without needing to define a separate task simply to add the env variable.
task local {
run { systemProperty "spring.profiles.active", "local" }
}
bootRun.mustRunAfter local
Then run gradle command as:
gradle bootRun local
There is no generic way to pass system properties to a task. In a nutshell, it's only supported for tasks that fork a separate JVM.
The bootRunLocal task (as defined above) will not execute in a separate JVM, and calling execute() on a task isn't supported (and would have to happen in the execution phase in any case). Tests, on the other hand, are always executed in a separate JVM (if executed by a Test task). To set system properties for test execution, you need to configure the corresponding Test task(s). For example:
test {
systemProperty "spring.profiles.active", "local"
}
For more information, see Test in the Gradle Build Language Reference.
SPRING_PROFILES_ACTIVE=local gradle clean bootRun
This is according to this and this and it works.
According to the spring-boot-gradle-plugin documentation you should be able to pass arguments like this
./gradlew bootRun --args='--spring.profiles.active=dev'
Seems like this is a new gradle feature since 4.9. I used it in my project and it worked out of the box.
For gradle 2.14 below example works.
I have added as below.
When System.properties['spring.profiles.active'] is null then default profile is set.
bootRun {
systemProperty 'spring.profiles.active', System.properties['spring.profiles.active']
}
command line example
gradle bootRun -Dspring.profiles.active=dev
Just for reference if anyone will have this issue:
Vlad answer didn't quite worked for me but this one works great with 2.4,
task local <<{
bootRun { systemProperty "spring.profiles.active", "local" }
}
local.finalizedBy bootRun
then gradle local
Responding to OP's exact request here ...
How do I pass spring.profiles.active system property to the bootRun plugin's task?
And assuming by "pass" the OP meant "pass from commandline" or "pass from IDE invocation" ... This is how I like to do it.
Add this to build.gradle:
/**
* Task from spring-boot-gradle-plugin, configured for easier development
*/
bootRun {
/* Lets you pick Spring Boot profile by system properties, e.g. gradle bootRun -Dspring.profiles.active=dev */
systemProperties = System.properties
}
Then when you invoke it, use the familiar Java flag for setting a system property
gradle bootRun -Dspring.profiles.active=local
There is one main advantage of sticking to system properties, over the environment variables option (SPRING_PROFILES_ACTIVE=local gradle bootRun) ... and that's easy portability between Linux/OS X (bash, etc.) and Windows (cmd.exe anyway).
I learned this way from this blog post.
(UPDATE: Ah somehow I had missed #Erich's response with same recommendation. Oops! I'm leaving my answer, because of the additional details about portability, etc.)
You can create a new task (in discussed case with name bootRunLocal), that would extend org.springframework.boot.gradle.run.BootRunTask and setup properties before task execution. You can create such a task with following code:
task bootRunLocal(type: org.springframework.boot.gradle.run.BootRunTask) {
doFirst() {
main = project.mainClassName
classpath = sourceSets.main.runtimeClasspath
systemProperty "spring.profiles.active", "local"
}
}
More details can be found here:
https://karolkalinski.github.io/gradle-task-that-runs-spring-boot-aplication-with-profile-activated/
Starting from SpringBoot 2.0.0-M5 setSystemProperties() is no longer a method of the task bootRun.
The build.gradle needs to be updated to
bootRun {
execSpec {
// System.properties["spring.profiles.active"]
systemProperties System.properties
}
}
This is as springBoot's run task uses org.gradle.process.JavaExecSpec
This works for me using Gradle 4.2
This works:
SPRING_PROFILES_ACTIVE=production ./gradlew app-service:bootRun
with run command you can add to build file run { systemProperties = System.properties } and start with gradle run -Dspring.profiles.active=local
Another way which doesn't require any support from the gradle task: Set the JAVA_TOOL_OPTIONS environment variable:
JAVA_TOOL_OPTIONS='-Dfoo=bar' gradle ...
Or if the variable might already contain anything useful:
JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -Dfoo=bar" gradle ...
// defualt value
def profiles = 'dev'
bootRun {
args = ["--spring.profiles.active=" + profiles]
}
Then you can simply pick a specific version when starting a gradle task, like
./gradlew bootRun -P dev
"dev" is gonna to take place "prod"

Resources