How should I be handling passing system properties from Gradle to my tests

Hello,

I need some help configuring my test tasks.

I have a Selenium test framework that I am using with Gradle. You can find the basics of it here.

https://github.com/iainrose/page-objects

In my BaseTest class, which all my other tests inherit from, I define a number of system properties so I can run the tests on different web servers, browsers, selenium servers, etc.

https://github.com/iainrose/page-objects/blob/master/src/test/java/BaseTest.java

Most of the time, I want to run the tests with the default values as defined in my BaseTest class but from time to time I need to run them using different settings.

I’ve noticed that unless I duplicate the declaration of those system properties within my test task definitions in build.gradle I cannot pass in other values from the command line at runtime.

Example:

With my test task configured like this …

test {
    useTestNG()
    maxParallelForks = 4
}

… this still runs my tests in Firefox

./gradlew test -DBROWSER=chrome

However, if I configure my test task like this it works and the tests will run in Chrome.

test {
    useTestNG()
    maxParallelForks = 4
    systemProperties = [
            BROWSER: System.getProperty('BROWSER', 'firefox')
    ]
}

You can see here that I’ve had to duplicate this in all of my tasks.

https://github.com/iainrose/page-objects/blob/master/build.gradle

This also just a dummy project and in the real one I have more than 3 tasks, and also will override more than just the one system property and it just seems wrong that I have to copy and paste this in every single test task. It seems even more wrong as the default value of BROWSER that I have to add and duplicate is never actually needed as if I just run …

./gradlew test

… the test will run in Firefox regardless of which of the above two version of my test task definition I use.

I must be missing something simple, can you please help me out?

Thanks for the quick reply Peter.

So does that mean I will always need to tell Gradle about every system parameter that I might need to override at some point? I can’t just get it to pass on whatever I set in the command line when I run the tests?

If so, the first option looks like it might do what I want but will I still be able to override that value in a single task if I need?

Example:

tasks.withType(Test) { systemProperty 'BROWSER', System.getProperty('BROWSER', 'firefox') }
  task alwaysRunInFirefox1(type: Test) {
    useTestNG() {
    }
}
  task alwaysRunInFirefox2(type: Test) {
    useTestNG() {
    }
}
  task alwaysRunInChrome(type: Test) {
    useTestNG() {
    }
    systemProperties = [
            BROWSER: System.getProperty('BROWSER', 'chrome')
    ]
}

What you are trying to do is to set system properties for the test JVM(s), not the Gradle JVM. That’s why you have to add some code to propagate system properties from the latter to the former. Gradle doesn’t do that automatically because it could have adverse effects on tests. As I showed, it’s simple to propagate all system properties if desired.

Of course you can always override the task configuration rule (your first line) for selected tasks. You could potentially save some code by creating those special tasks in a loop.

1 Like

Thanks Peter, I understand now.

I read through this thread and it doesn’t work for me. Can anyone tell me what is wrong with this snippet? It always returns the default of ‘1’ on a 4 processor Windows system even though the system variable is clearly set to ‘4’ in the global system environment.

tasks.withType(Test) {
    // get System properties needed for tests
    systemProperties['NUMBER_OF_PROCESSORS'] =
            System.getProperty("NUMBER_OF_PROCESSORS", "1")
 //systemProperties = System.getProperties()
        //systemProperties = System.properties
 println 'NUMBER_OF_PROCESSORS is ' +
         systemProperties['NUMBER_OF_PROCESSORS'] // always returns 1
}

Here is my GitHub project that reproduces this problem: https://github.com/djangofan/GradleProps

even though the system variable is clearly set to ‘4’ in the global system environment

I think you’re confusing JVM system properties and environment variables.

I ran into the same issue so I created a small sample project on GitHub to demonstrate how to accomplish this. It also shows how to reference those system properties passed from the build jvm to the test jvm in a Spring application context ('cause this was my challenge). See: https://github.com/mvcatsifma/spring-ctx-props-file

Great stuff, much appreciated.

Gradle makes it really easy to configure multiple tasks at once:

tasks.withType(Test) { systemProperty 'BROWSER', System.getProperty('BROWSER', 'firefox') }

Likewise, you can propagate all system properties with ‘systemProperties = System.getProperties()’.

1 Like