Part 4 - Passing Properties into Gradle and Cucumber

Part 4 - Passing Properties into Gradle and Cucumber

·

4 min read

View:

Introduction

OK, now we've got a basic framework, before we go too much further we probably want to be able to pass in properties to the test run. This is super useful for passing in configuration differences across Jenkins runs, for example, one job for one browser, and another job for a different browser. It is also useful when running tests locally to easily override properties if need be.

I'm going to build upon the project in Part 3 above but will change the project name to keep it separate (both locally and in GIT).

Project vs System Property

Project properties are internal to Gradle and won't "leak" out into other applications/processes running on the same system. System properties are as the name suggests, system-wide so other applications could access the properties. Generally, not a big deal if you are running on specific Docker instances or a closed test environment, but something to be aware of nonetheless.

Primarily, I use a project property to pass a value in when running Gradle and then set a system property that the test can then use. I also have an example of how to do it with just system properties, however.

The Code

OK, so first, we want to set a Gradle project property for the passed-in property. In build.gradle.kts, add the following above the definition of the task:


val propOne=project.properties["propOne"]

tasks {
// ... rest of existing task code
}

The names can be whatever you wish. OK so now we have set a variable in our Kotlin script from the value passed in as a project property. Let's use it in our Cucumber test.

From here, in the runCucumber function, use the propOne variable to set a system property for the JavaExec task:

fun runCucumber(){
        // existing unchanged code

        // === add: set the system properties to be passed-in to the test
        systemProperty("prop.one", propOne)
        // eof add
    }
}

Why?

Because the runCucumber function launches Cucumber via JavaExec, any properties passed in as a system property up until that point won't be available in the new instance of the JVM and will be null when we try and use them in our Java code.

Instead, we need to set a system property for the new JVM instance that is running our test. This is the case whether or not you are using a system or project property to pass the original variable into the test.

Let's use the propOne project property in our Java code. Open src/test/java/com.slashqa/StepDefinitionsPartTwo and add the following code:

    @Then("the user verifies that the string stored in the session is {string}")
    public void verifyVariable(String expectedValue){
        // === add
        if(null!=System.getProperty("prop.one")) {
            System.out.println("The property passed in was: " + System.getProperty("prop.one"));
        }
        // eof add
        assertEquals(expectedValue, getSession().get(SessionUtils.TEST_KEY));
    }

Run the test via Gradle (not Cucumber for Java just yet) and you should see the property value is passed through to the method and subsequently output to the console:

Not seeing any output? By default, Gradle won't output standard out and standard error for tests. You can enable this by adding the following to the runTest task:

    val runTest by registering(Test::class) {
        doLast {
            runCucumber()
        }
        // === add
        this.testLogging.showStandardStreams = true
        outputs.upToDateWhen {false}
        // eof add
    }

What about Cucumber for Java?

For those eagle-eyed readers, you'll notice that the property will never be set at the moment when the test is run via Cucumber for Java. Simply pass the same property (using the same name as the Java code, in this case prop.one) in via the VM Options input:

Run it, and you should correctly see it in the following output:

Using System Properties Only

Alternative to project property:

If you wanted to use a system property instead of a project property, you could do something along the lines of:

fun runCucumber(){
        // existing unchanged code

        // === add: set the system properties to be passed-in to the test
        systemProperty("prop.one", System.getProperty("propOne"))
        // eof add
    }
}

When running it via the gradle wrapper on the command line, you would pass your property with -D instead of -P, for example:

./gradlew runTest -DpropOne="This is a system property"

This project is available on my GIT repo:

https://github.com/slashqa/slashqa-cucumber-with-system-properties

OK, that's it. If it has helped you please let me know. Michael.