Skip to main content

Gradle Build Support

TestFly works with Gradle out of the box — the JAR on Maven Central is build-tool-agnostic. This page covers the recommended setup for both Groovy DSL (build.gradle) and Kotlin DSL (build.gradle.kts).


Step 1 — Add the dependency​

build.gradle
plugins {
id 'java'
}

repositories {
mavenCentral()
}

dependencies {
testImplementation 'io.github.hakanngul:testfly:1.0.7'
}

Step 2 — Configure test execution​

TestNG (default runner)​

build.gradle
test {
useTestNG {
// Optional: point to a testng.xml suite file
// suites 'src/test/resources/testng.xml'
}

// Forward system properties so -Dtestfly.profile=staging works from the CLI
systemProperties System.properties

// Display test output in the console
testLogging {
events 'passed', 'skipped', 'failed'
showStandardStreams = false
}
}

JUnit 5 bridge​

If you're using BaseJUnit5Test or @EnableTestFly:

build.gradle
dependencies {
testImplementation 'io.github.hakanngul:testfly:1.0.7'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.2'
}

test {
useJUnitPlatform()
systemProperties System.properties
}

Step 3 — Configuration file​

Create testfly.yml at the project root (same level as build.gradle):

testfly.yml
execution:
mode: local
baseUrl: https://example.com

browser:
name: chrome
headless: true

timeouts:
explicit: 10
pageLoad: 30

retry:
enabled: true
maxAttempts: 2

Running tests​

# Run all tests
./gradlew test

# Run a single test class
./gradlew test --tests "com.example.LoginTest"

# Run a single test method
./gradlew test --tests "com.example.LoginTest.validLogin"

# Run with an environment profile
./gradlew test -Dtestfly.profile=staging

# Pass multiple JVM args
./gradlew test -Dbrowser.name=firefox -Dbrowser.headless=true

Test report locations​

Report typeGradle path
HTML report (TestFly)build/testfly-report/index.html
JUnit XML (TestFly)build/test-results/test/TEST-TestFly.xml
Gradle's own HTML reportbuild/reports/tests/test/index.html
Allure results (if enabled)build/allure-results/
JUnit XML auto-detection

TestFly automatically detects Gradle by checking whether a build/ directory exists and target/ does not, then writes XML to build/test-results/test/. Override with -Dtestfly.reports.dir=path/to/dir if needed.


Parallel execution​

For parallel runs with Gradle, configure the test task alongside testfly.yml:

build.gradle
test {
useTestNG()
maxParallelForks = 4 // Gradle worker processes
systemProperties System.properties
}
testfly.yml
execution:
parallel: methods
threadCount: 4

Optional dependencies​

These are compileOnly / optional in the TestFly JAR — add them only if you use the corresponding feature:

FeatureDependency
Excel @TestDatatestImplementation 'org.apache.poi:poi-ooxml:5.4.0'
Email verification (IMAP)testImplementation 'com.sun.mail:jakarta.mail:2.0.2'
CucumbertestImplementation 'io.cucumber:cucumber-java:7.20.1' + testImplementation 'io.cucumber:cucumber-junit-platform-engine:7.20.1'

Full example project​

A minimal working Gradle project (Groovy DSL, TestNG):

my-tests/
├── build.gradle
├── testfly.yml
└── src/
└── test/
└── java/
└── com/example/
└── LoginTest.java
build.gradle
plugins {
id 'java'
}

repositories {
mavenCentral()
}

dependencies {
testImplementation 'io.github.hakanngul:testfly:1.0.7'
}

test {
useTestNG()
systemProperties System.properties
testLogging { events 'passed', 'skipped', 'failed' }
}
src/test/java/com/example/LoginTest.java
import io.testfly.test.BaseTest;
import org.openqa.selenium.By;
import org.testng.annotations.Test;

public class LoginTest extends BaseTest {

@Test
public void validLogin() {
open("/login");
find("input#username").type("admin");
find("input#password").type("secret");
find("button[type='submit']").click();
assertThat(By.id("dashboard")).isVisible();
}
}
./gradlew test