---
title: "Integration with Gradle"
canonical: "https://docs.getxray.app/space/XRAY/301663117/Integration%20with%20Gradle"
format: markdown
---
![image](media://ea9a156b-7766-4685-9249-b655cfc6fdb3)


> Macro (toc)

# Overview

[Gradle](https://docs.gradle.org/current/userguide/userguide.html) is an open-source build tool that provides flexibility, and performance through task parallelization. Gradle is known in Java projects, as an alternative to Maven, but also supports other languages. Find out more about its [features](https://gradle.org/features/) on Gradle's site. 

Integration with Xray is possible using Xray APIs, namely the [REST API for importing test results](https://getxraydocs.atlassian.net/wiki/spaces/XRAY/pages/301667997).

<span style="color: #172B4D">You can use this integration to upload test results to Xray, in one of the supported test reports/formats, so that you have visibility of your test results from your pipeline in Jira.</span>

<span style="color: #172B4D">The examples detailed on this page are available in a </span>[<span style="color: #172B4D">GitHub repo</span>](https://github.com/Xray-App/tutorials-java-gradle)<span style="color: #172B4D">. They are not exhaustive; please consider them just as a reference and feel free to adapt them to your needs.</span>

# <span style="color: #172B4D">How to use</span>

<span style="color: #172B4D">The following examples were made using Gradle 7.4.2 and</span>[<span style="color: #172B4D"> </span>](https://getxraydocs.atlassian.net/wiki/pages/editpage.action?pageId=44834374)<span style="color: #172B4D">JDK 11.</span>

<span style="color: #172B4D">In order to invoke the REST API, we'll use the </span>`curl`<span style="color: #172B4D"> utility that is available on Unix, Linux, macOS, and other systems.</span>

<span style="color: #172B4D">We don't need to install any specific Gradle plugin for this.</span>

<span style="color: #172B4D">To import the results we use a custom Gradle task. We can then either invoke it by using </span>`gradle`<span style="color: #172B4D"> or </span>`gradlew`<span style="color: #172B4D"> (i.e., </span>[<span style="color: #172B4D">Gradle Wrapper</span>](https://docs.gradle.org/current/userguide/gradle_wrapper.html)<span style="color: #172B4D">).</span>

## <span style="color: #172B4D">Configuration</span>

<span style="color: #172B4D">Our task will make use of several variables.</span>

<span style="color: #172B4D">In Gradle, we can define some variables within the tasks themselves, and they will be instantiated during the configuration phase.</span>

<span style="color: #172B4D">Another option is to use a </span>`gradle.properties`<span style="color: #172B4D"> file, such as the following example.</span>


<details>
<summary>example of gradle.properties</summary>

```
# Jira server/DC specifics
jiraBaseUrl=https://jiraserver.local
jiraUsername=someuser
jiraPassword=somepass

reportFormat=junit
projectKey=CALC
version=v1.0
revision=123
testPlanKey=CALC-726
testExecKey=
testEnvironment=
```
</details>


<span style="color: #172B4D">Gradle will pick it and these variables will be available for the task(s) that we will use/implement.</span>

## <span style="color: #172B4D">Examples</span>

### <span style="color: #172B4D">JUnit4</span>

<span style="color: #172B4D">In this </span>[<span style="color: #172B4D">example</span>](https://github.com/Xray-App/tutorials-java-gradle/tree/main/junit4_basic)<span style="color: #172B4D">, the</span><span style="color: #24292f"> tests are implemented using Java + JUnit 4.13.x.</span>

We use a configuration file to define the REST API specifics (<span style="color: #172B4D">i.e.,</span><span style="color: #172B4D"> </span>Jira server/DC URL along with a Jira username and password) and some parameters to identify, for example, the target project and version/release of the SUT.

In this case, we're using the standard JUnit endpoint (more info on the endpoint and the supported parameters is available in [Import Execution Results - REST](https://getxraydocs.atlassian.net/wiki/spaces/XRAY/pages/301667997)).

<details>
<summary>gradle.properties</summary>

```
# Jira server/DC specifics
jiraBaseUrl=https://jiraserver.local
jiraUsername=someuser
jiraPassword=somepass

reportFormat=junit
projectKey=CALC
version=v1.0
revision=123
testPlanKey=CALC-726
testExecKey=
testEnvironment=
```
</details>


<span style="color: #24292f">We then generate a "standard" JUnit XML report and use a custom task to perform the REST API request that submits the results to Xray.</span>

<span style="color: #24292f">The following example shows a </span>`build.gradle`<span style="color: #24292f"> file with a custom task named </span>**<span style="color: #24292f">importJUnitResultsToXrayDC</span>**<span style="color: #24292f"> where we implement the logic to push the results to Xray.</span>

<span style="color: #24292f">The </span>`test`<span style="color: #24292f"> task uses the JUnit4 runner by declaring </span>`useJUnit().`

<details>
<summary>build.gradle</summary>

```groovy
apply plugin: 'java'

repositories {
    mavenCentral()
}

jar {
    archiveBaseName = 'tutorial-gradle-junit4-basic'
    archiveVersion =  '0.1.0'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

tasks.withType(JavaCompile) {
    options.compilerArgs += '-Xlint:deprecation'
}

test {
    useJUnit()
    reports {
	    // destination = file('build/test-results/folder')
        junitXml.required = true
        html.required = false
    }
    ignoreFailures = true
}

dependencies {
    testImplementation 'junit:junit:4.13.2'
    testImplementation 'org.hamcrest:hamcrest-library:2.2'
}

configurations.all {
    resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
    resolutionStrategy.cacheDynamicVersionsFor 0, 'seconds'
}

task importJUnitResultsToXrayDC(type: Exec) {
	description 'Imports Junit test results to Xray Test Management for Jira DC.'
	dependsOn 'test' 

    // the following variables can be defined locally or in gradle.properties
    //  - jiraBaseUrl, jiraUsername, jiraPassword
    //  - reportFormat, projectKey version, revision, testPlanKey, testExecKey, testEnvironment

	def reportFile = "build/test-results/test/TEST-app.getxray.java.CalcTest.xml"

	def url = "${jiraBaseUrl}/rest/raven/2.0/import/execution/${reportFormat}?"
	if (projectKey?.trim()) {
		url += "&projectKey=${projectKey}"
	}
	if (version?.trim()) {
		url += "&fixVersion=${version}"
	}
	if (revision?.trim()) {
		url += "&revision=${revision}"
	}
	if (testPlanKey?.trim()) {
		url += "&testPlanKey=${testPlanKey}"
	}
	if (testExecKey?.trim()) {
		url += "&testExecKey=${testExecKey}"
	}
	if (testEnvironment?.trim()) {
		url += "&testEnvironments=${testEnvironment}"
	}

    commandLine 'curl', '--fail-with-body', '-H','Content-Type: multipart/form-data', '-u', "${jiraUsername}:${jiraPassword}", '-F', "file=@${reportFile}", url

    //store the output instead of printing to the console:
    standardOutput = new ByteArrayOutputStream()
    ignoreExitValue = false //true

    doLast {
            if (execResult.getExitValue() != 0) {
                    println "ERROR: problem importing results to Xray"
            } else {
                    println "Results imported to Xray!"
            }
            println  standardOutput.toString()
    }
}

```
</details>


To run the tests and import them to Xray we can run Gradle as usual and add the name of the task we created earlier. 

```shell
gradle clean compileJava test importJUnitResultsToXrayDC
```


In Xray, a Test Execution will be created accordingly.

![image](media://1c4247f2-30d7-4060-94b3-b3791a63c328)

### <span style="color: #172B4D">JUnit5</span>

<span style="color: #172B4D">In this </span>[<span style="color: #172B4D">example</span>](https://github.com/Xray-App/tutorials-java-gradle/tree/main/junit5_basic)<span style="color: #172B4D">, the</span><span style="color: #24292f"> tests are implemented using Java + JUnit 5.8.x.</span>

We use a configuration file to define the REST API specifics (<span style="color: #172B4D">i.e.,</span><span style="color: #172B4D"> </span>Jira server/DC URL along with a Jira username and password) and some parameters to identify, for example, the target project and version/release of the SUT.

In this case, we're using the standard JUnit endpoint (more info on the endpoint and the supported parameters is available in [Import Execution Results - REST](https://getxraydocs.atlassian.net/wiki/spaces/XRAY/pages/301667997)).

<details>
<summary>gradle.properties</summary>

```
# Jira server/DC specifics
jiraBaseUrl=https://jiraserver.local
jiraUsername=someuser
jiraPassword=somepass

reportFormat=junit
projectKey=CALC
version=v1.0
revision=123
testPlanKey=CALC-726
testExecKey=
testEnvironment=
```
</details>


<span style="color: #24292f">We then generate a "standard" JUnit XML report and use a custom task to perform the REST API request that submits the results to Xray.</span>

<span style="color: #24292f">The following example shows a </span>`build.gradle`<span style="color: #24292f"> file with a custom task named </span>**<span style="color: #24292f">importJUnitResultsToXrayDC</span>**<span style="color: #24292f"> where we implement the logic to push the results to Xray. </span>

<span style="color: #24292f">The </span>`test`<span style="color: #24292f"> task uses the JUnit5 platform runner by declaring </span>`useJUnitPlatform().`

<details>
<summary>build.gradle</summary>

```groovy
apply plugin: 'java'

repositories {
    mavenCentral()
}

jar {
    archiveBaseName = 'tutorial-gradle-junit5-basic'
    archiveVersion =  '0.1.0'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

test {
    useJUnitPlatform()
    reports {
	    // destination = file('build/test-results/folder')
        junitXml.required = true
        html.required = false
    }
    ignoreFailures = true
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testImplementation 'org.hamcrest:hamcrest-library:2.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

configurations.all {
    resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
    resolutionStrategy.cacheDynamicVersionsFor 0, 'seconds'
}

task importJUnitResultsToXrayDC(type: Exec) {
	description 'Imports Junit test results to Xray Test Management for Jira DC.'
	dependsOn 'test' 

    // the following variables can be defined locally or in gradle.properties
    //  - jiraBaseUrl, jiraUsername, jiraPassword
    //  - reportFormat, projectKey version, revision, testPlanKey, testExecKey, testEnvironment

	def reportFile = "build/test-results/test/TEST-app.getxray.java.CalcTest.xml"

	def url = "${jiraBaseUrl}/rest/raven/2.0/import/execution/${reportFormat}?"
	if (projectKey?.trim()) {
		url += "&projectKey=${projectKey}"
	}
	if (version?.trim()) {
		url += "&fixVersion=${version}"
	}
	if (revision?.trim()) {
		url += "&revision=${revision}"
	}
	if (testPlanKey?.trim()) {
		url += "&testPlanKey=${testPlanKey}"
	}
	if (testExecKey?.trim()) {
		url += "&testExecKey=${testExecKey}"
	}
	if (testEnvironment?.trim()) {
		url += "&testEnvironments=${testEnvironment}"
	}

    commandLine 'curl', '--fail-with-body', '-H','Content-Type: multipart/form-data', '-u', "${jiraUsername}:${jiraPassword}", '-F', "file=@${reportFile}", url

    //store the output instead of printing to the console:
    standardOutput = new ByteArrayOutputStream()
    ignoreExitValue = false //true

    doLast {
            if (execResult.getExitValue() != 0) {
                    println "ERROR: problem importing results to Xray"
            } else {
                    println "Results imported to Xray!"
            }
            println  standardOutput.toString()
    }
}


```
</details>


To run the tests and import them to Xray we can run gradle as usual and add the name of the task we created earlier. 

```shell
gradle clean compileJava test importJUnitResultsToXrayDC
```


In Xray, a Test Execution will be created accordingly.

![image](media://bb57f4d6-7cbd-4c87-ab4d-298c5aaab0f3)

### <span style="color: #172B4D">JUnit5 with additional information </span>

<span style="color: #172B4D">In this </span>[<span style="color: #172B4D">example</span>](https://github.com/Xray-App/tutorials-java-gradle/tree/main/junit5_enhanced)<span style="color: #172B4D">, the</span><span style="color: #24292f"> tests are implemented using Java + JUnit 5.8.x.</span>


> ℹ️ <span style="color: #24292f">In this case, we'll use the </span>[<span style="color: #24292f">enhanced capabilities that Xray provides for JUnit</span>](https://getxraydocs.atlassian.net/wiki/spaces/XRAY/pages/301506710)<span style="color: #24292f"> allowing you to provide additional information during the execution of the tests, including screenshots and others; to do so, we'll use the </span>[<span style="color: #24292f">xray-junit-extensions</span>](https://github.com/Xray-App/xray-junit-extensions)<span style="color: #24292f"> package.</span>


We use a configuration file to define the REST API specifics (<span style="color: #172B4D">i.e.,</span><span style="color: #172B4D"> </span>Jira server/DC URL along with a Jira username and password) and some parameters to identify, for example, the target project and version/release of the SUT.

In this case, we're using the standard JUnit endpoint (more info on the endpoint and the supported parameters is available in [Import Execution Results - REST](https://getxraydocs.atlassian.net/wiki/spaces/XRAY/pages/301667997)).

<details>
<summary>gradle.properties</summary>

```
# Jira server/DC specifics
jiraBaseUrl=https://jiraserver.local
jiraUsername=someuser
jiraPassword=somepass

reportFormat=junit
projectKey=CALC
version=v1.0
revision=123
testPlanKey=CALC-726
testExecKey=
testEnvironment=
```
</details>


<span style="color: #24292f">We then generate a "standard" JUnit XML report and use a custom task to perform the REST API request that submits the results to Xray.</span>

<span style="color: #24292f">The following example shows a </span>`build.gradle`<span style="color: #24292f"> file with a custom task named </span>**<span style="color: #24292f">importJUnitResultsToXrayDC</span>**<span style="color: #24292f"> where we implement the logic to push the results to Xray. </span>

<span style="color: #24292f">The </span>`test`<span style="color: #24292f"> task uses the JUnit5 platform runner by declaring </span>`useJUnitPlatform().`

<details>
<summary>build.gradle</summary>

```groovy
apply plugin: 'java'

repositories {
    mavenCentral()
}

jar {
    archiveBaseName = 'tutorial-gradle-junit5-enhanced'
    archiveVersion =  '0.1.0'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

test {
    useJUnitPlatform()
    reports {
	// destination = file('build/test-results/folder')
        junitXml.required = true
        html.required = false
    }
    ignoreFailures = true
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testImplementation 'org.hamcrest:hamcrest-library:2.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
    testImplementation 'app.getxray:xray-junit-extensions:0.6.1'
}

configurations.all {
    resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
    resolutionStrategy.cacheDynamicVersionsFor 0, 'seconds'
}

task importJUnitResultsToXrayDC(type: Exec) {
	description 'Imports Junit test results to Xray Test Management for Jira DC.'
	dependsOn 'test' 

    // the following variables can be defined locally or in gradle.properties
    //  - jiraBaseUrl, jiraUsername, jiraPassword
    //  - reportFormat, projectKey version, revision, testPlanKey, testExecKey, testEnvironment

	def reportFile = "reports/TEST-junit-jupiter.xml"

	def url = "${jiraBaseUrl}/rest/raven/2.0/import/execution/${reportFormat}?"
	if (projectKey?.trim()) {
		url += "&projectKey=${projectKey}"
	}
	if (version?.trim()) {
		url += "&fixVersion=${version}"
	}
	if (revision?.trim()) {
		url += "&revision=${revision}"
	}
	if (testPlanKey?.trim()) {
		url += "&testPlanKey=${testPlanKey}"
	}
	if (testExecKey?.trim()) {
		url += "&testExecKey=${testExecKey}"
	}
	if (testEnvironment?.trim()) {
		url += "&testEnvironments=${testEnvironment}"
	}

    commandLine 'curl', '--fail-with-body', '-H','Content-Type: multipart/form-data', '-u', "${jiraUsername}:${jiraPassword}", '-F', "file=@${reportFile}", url 

    //store the output instead of printing to the console:
    standardOutput = new ByteArrayOutputStream()
    ignoreExitValue = false //true

    doLast {
            if (execResult.getExitValue() != 0) {
                    println "ERROR: problem importing results to Xray"
            } else {
                    println "Results imported to Xray!"
            }
            println  standardOutput.toString()
    }
}


```
</details>


To run the tests and import them to Xray we can run Gradle as usual and add the name of the task we created earlier. 

```shell
gradle clean compileJava test importJUnitResultsToXrayDC
```


In Xray, a Test Execution will be created accordingly.

![image](media://412ed117-f87c-45e1-8e7e-6209d83c80f7)

### <span style="color: #172B4D">TestNG</span>

<span style="color: #172B4D">In this </span>[<span style="color: #172B4D">example</span>](https://github.com/Xray-App/tutorials-java-gradle/tree/main/testng_basic)<span style="color: #172B4D">, the</span><span style="color: #24292f"> tests are implemented using Java + TestNG 7.6.x.</span>


We use a configuration file to define the REST API specifics (<span style="color: #172B4D">i.e.,</span><span style="color: #172B4D"> </span>Jira server/DC URL along with a Jira username and password) and some parameters to identify, for example, the target project and version/release of the SUT.

In this case, we're using the standard TestNG endpoint (more info on the endpoint and the supported parameters is available in [Import Execution Results - REST](https://getxraydocs.atlassian.net/wiki/spaces/XRAY/pages/301667997)).

<details>
<summary>gradle.properties</summary>

```
# Jira server/DC specifics
jiraBaseUrl=https://jiraserver.local
jiraUsername=someuser
jiraPassword=somepass

reportFormat=testng
projectKey=CALC
version=v1.0
revision=123
testPlanKey=CALC-726
testExecKey=
testEnvironment=
```
</details>


<span style="color: #24292f">We then generate a "standard" TestNG XML report and use a custom task to perform the REST API request that submits the results to Xray.</span>

<span style="color: #24292f">The following example shows a </span>`build.gradle`<span style="color: #24292f"> file with a custom task named </span>**<span style="color: #24292f">importTestNGResultsToXrayDC</span>**<span style="color: #24292f"> where we implement the logic to push the results to Xray. </span>

<span style="color: #24292f">The </span>`test`<span style="color: #24292f"> task uses the TestNG runner by declaring </span>`useTestNG().`

<details>
<summary>build.gradle</summary>

```groovy
apply plugin: 'java'

repositories {
    mavenCentral()
}

jar {
    archiveBaseName = 'tutorial-gradle-testng-basic'
    archiveVersion =  '0.1.0'
}

sourceCompatibility = 11
targetCompatibility = 11

test {
    useTestNG() {
         // report generation delegated to TestNG library:
         useDefaultListeners = true
    }
    reports {
         junitXml.required = false
         html.required = false
    }
    ignoreFailures = true
}

dependencies {
    testImplementation 'org.testng:testng:7.6.1'
}

configurations.all {
    resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
    resolutionStrategy.cacheDynamicVersionsFor 0, 'seconds'
}

task importTestNGResultsToXrayDC(type: Exec) {
	description 'Imports TestNG test results to Xray Test Management for Jira DC.'
	dependsOn 'test' 

    // the following variables can be defined locally or in gradle.properties
    //  - jiraBaseUrl, jiraUsername, jiraPassword
    //  - reportFormat, projectKey version, revision, testPlanKey, testExecKey, testEnvironment

	def reportFile = "build/reports/tests/test/testng-results.xml"

	def url = "${jiraBaseUrl}/rest/raven/2.0/import/execution/${reportFormat}?"
	if (projectKey?.trim()) {
		url += "&projectKey=${projectKey}"
	}
	if (version?.trim()) {
		url += "&fixVersion=${version}"
	}
	if (revision?.trim()) {
		url += "&revision=${revision}"
	}
	if (testPlanKey?.trim()) {
		url += "&testPlanKey=${testPlanKey}"
	}
	if (testExecKey?.trim()) {
		url += "&testExecKey=${testExecKey}"
	}
	if (testEnvironment?.trim()) {
		url += "&testEnvironments=${testEnvironment}"
	}

    commandLine 'curl', '--fail-with-body', '-H','Content-Type: multipart/form-data', '-u', "${jiraUsername}:${jiraPassword}", '-F', "file=@${reportFile}", url

    //store the output instead of printing to the console:
    standardOutput = new ByteArrayOutputStream()
    ignoreExitValue = false //true

    doLast {
            if (execResult.getExitValue() != 0) {
                    println "ERROR: problem importing results to Xray"
            } else {
                    println "Results imported to Xray!"
            }
            println  standardOutput.toString()
    }
}


```
</details>


To run the tests and import them to Xray we can run gradle as usual and add the name of the task we created earlier. 

```shell
gradle clean compileJava test importTestNGResultsToXrayDC
```


In Xray, a Test Execution will be created accordingly.

![image](media://29915edc-c1da-46dc-a1f7-96e860bdcc94)

### <span style="color: #172B4D">TestNG with additional information </span>

<span style="color: #172B4D">In this </span>[<span style="color: #172B4D">example</span>](https://github.com/Xray-App/tutorials-java-gradle/tree/main/testng_enhanced)<span style="color: #172B4D">, the</span><span style="color: #24292f"> tests are implemented using Java + TestNG 7.6.x.</span>


> ℹ️ <span style="color: #24292f">In this case, we'll use the </span>[<span style="color: #24292f">enhanced capabilities that Xray provides for TestNG</span>](https://getxraydocs.atlassian.net/wiki/spaces/XRAY/pages/301703168)<span style="color: #24292f"> allowing you to provide additional information during the execution of the tests, including screenshots and others; to do so, we'll use the </span>[<span style="color: #24292f">xray-testng-extensions</span>](https://github.com/bitcoder/xray-testng-extensions)<span style="color: #24292f"> package.</span>


We use a configuration file to define the REST API specifics (<span style="color: #172B4D">i.e.,</span><span style="color: #172B4D"> </span>Jira server/DC URL along with a Jira username and password) and some parameters to identify, for example, the target project and version/release of the SUT.

In this case, we're using the standard TestNG endpoint (more info on the endpoint and the supported parameters is available in [Import Execution Results - REST](https://getxraydocs.atlassian.net/wiki/spaces/XRAY/pages/301667997)).

<details>
<summary>gradle.properties</summary>

```
# Jira server/DC specifics
jiraBaseUrl=https://jiraserver.local
jiraUsername=someuser
jiraPassword=somepass

reportFormat=testng
projectKey=CALC
version=v1.0
revision=123
testPlanKey=CALC-726
testExecKey=
testEnvironment=
```
</details>


<span style="color: #24292f">We then generate a "standard" TestNG XML report and use a custom task to perform the REST API request that submits the results to Xray.</span>

<span style="color: #24292f">The following example shows a </span>`build.gradle`<span style="color: #24292f"> file with a custom task named </span>**<span style="color: #24292f">importTestNGResultsToXrayDC</span>**<span style="color: #24292f"> where we implement the logic to push the results to Xray. </span>

<span style="color: #24292f">In this case, we won't be using the built-in </span>`test`<span style="color: #24292f"> task; instead, we implement a custom one named </span>`testngTest`<span style="color: #24292f"> as we need to provide additional parameters to the XMLReporter class provided by TestNG that otherwise is not yet possible; this is what enables the feature of embedding additional attributes on the TestNG XML report that Xray can take advantage of.</span>

<details>
<summary>build.gradle</summary>

```groovy
apply plugin: 'java'

repositories {
    mavenCentral()
}

jar {
    archiveBaseName = 'tutorial-gradle-testng-basic'
    archiveVersion =  '0.1.0'
}

sourceCompatibility = 11
targetCompatibility = 11

test {
    useTestNG()
    reports {
	    // destination = file('build/test-results/folder')
        junitXml.required = false
        html.required = false
    }
    ignoreFailures = true
}

repositories {
    mavenLocal()
    maven {
        url = uri('https://maven.xpand-it.com/artifactory/releases')
    }

    maven {
        url = uri('https://maven.pkg.github.com/bitcoder/*')
    }

    maven {
        url = uri('https://repo.maven.apache.org/maven2/')
    }
}

dependencies {
    testImplementation 'org.testng:testng:7.6.1'
    testImplementation 'com.xpandit.xray:xray-testng-extensions:1.1.0'
}

configurations.all {
    resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
    resolutionStrategy.cacheDynamicVersionsFor 0, 'seconds'
}

task testngTest(type: JavaExec, dependsOn: [classes]) {
    group 'Verification'
    description 'Run TestNG tests'
    ignoreExitValue = true // to not throw exception if test fails
    mainClass = 'org.testng.TestNG'
    args('testng.xml', '-reporter',
            'org.testng.reporters.XMLReporter:generateTestResultAttributes=true,generateGroupsAttribute=true'
    )
    classpath = sourceSets.test.runtimeClasspath
}

task importTestNGResultsToXrayDC(type: Exec) {
	description 'Imports TestNG test results to Xray Test Management for Jira DC.'
	dependsOn 'testngTest' 

    // the following variables can be defined locally or in gradle.properties
    //  - jiraBaseUrl, jiraUsername, jiraPassword
    //  - reportFormat, projectKey version, revision, testPlanKey, testExecKey, testEnvironment

	def reportFile = "test-output/testng-results.xml"

	def url = "${jiraBaseUrl}/rest/raven/2.0/import/execution/${reportFormat}?"
	if (projectKey?.trim()) {
		url += "&projectKey=${projectKey}"
	}
	if (version?.trim()) {
		url += "&fixVersion=${version}"
	}
	if (revision?.trim()) {
		url += "&revision=${revision}"
	}
	if (testPlanKey?.trim()) {
		url += "&testPlanKey=${testPlanKey}"
	}
	if (testExecKey?.trim()) {
		url += "&testExecKey=${testExecKey}"
	}
	if (testEnvironment?.trim()) {
		url += "&testEnvironments=${testEnvironment}"
	}

    commandLine 'curl', '--fail-with-body', '-H','Content-Type: multipart/form-data', '-u', "${jiraUsername}:${jiraPassword}", '-F', "file=@${reportFile}", url

    //store the output instead of printing to the console:
    standardOutput = new ByteArrayOutputStream()
    ignoreExitValue = false

    doLast {
            if (execResult.getExitValue() != 0) {
                    println "ERROR: problem importing results to Xray"
            } else {
                    println "Results imported to Xray!"
            }
            println  standardOutput.toString()
    }
}
```
</details>


To run the tests and import them to Xray we can run Gradle as usual and add the name of the task we created earlier. 

```shell
gradle clean compileJava testngTest importTestNGResultsToXrayDC
```


In Xray, a Test Execution will be created accordingly.

![image](media://241940c3-def1-4808-900a-4eb0968e119f)

# Tips

- To debug existing tasks, run your Gradle command with "–stacktrace"
- On the custom tasks that execute a command using exec, set `ignoreExitValue = false`

# References

- [Gradle documentation](https://docs.gradle.org/current/userguide/userguide.html)
- [Gradle vs Maven](https://stackify.com/gradle-vs-maven/#:~:text=Gradle%20and%20Maven%20fundamentally%20differ,%2C%20are%20the%20%E2%80%9Cworkhorses.%E2%80%9D)
- [Code for the examples showcasing the integration between Gradle and Xray](https://github.com/Xray-App/tutorials-java-gradle)