Skip to main content

Gradle Plugin

We maintain a Gradle plugin that uploads your Android app to TestingBot Storage and runs Espresso tests on TestingBot's real device cloud, straight from your build, with no curl scripts required.

  • testingbotUpload uploads an APK to TestingBot Storage and returns a reusable tb://<appkey> identifier.
  • testingbotEspresso uploads your app and instrumented test APK, runs Espresso across one or more devices, waits for the results, downloads a JUnit XML report, and fails the build on test failures.
  • testingbotDevices lists the Android devices available on your account.
  • Reads credentials from the DSL, Gradle properties or environment variables, and is configuration-cache compatible with no extra HTTP dependencies on your build classpath.

The plugin is published on the Gradle Plugin Portal and the source is available on GitHub.

Requirements

  • Gradle 8.0 or newer, running on JDK 17 or newer.
  • A TestingBot account. Grab your key and secret from the member area.

1. Installation

Apply the plugin in your Android app module's build file.

// build.gradle.kts
plugins {
    id("com.testingbot.gradle") version "0.1.0"
}

Using the Groovy DSL:

// build.gradle
plugins {
    id 'com.testingbot.gradle' version '0.1.0'
}

2. Credentials

Credentials are resolved in this order, first match wins:

  • The DSL: testingbot { key.set("…"); secret.set("…") }
  • Gradle properties: -Ptestingbot.key=… -Ptestingbot.secret=… (or in gradle.properties)
  • Environment variables: TESTINGBOT_KEY / TESTINGBOT_SECRET

In CI, prefer environment variables backed by secrets. Never commit credentials to your repository.

3. Usage

Configure the testingbot { } block with your APKs and the device capabilities you want to run on.

testingbot {
    // Credentials (optional here if provided via env vars / gradle properties)
    key.set(providers.environmentVariable("TESTINGBOT_KEY"))
    secret.set(providers.environmentVariable("TESTINGBOT_SECRET"))

    // The app + instrumented test APKs
    appApk.set(layout.projectDirectory.file("app/build/outputs/apk/debug/app-debug.apk"))
    testApk.set(
        layout.projectDirectory.file("app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk")
    )

    // One run is started per capability. Keys are passed through to TestingBot verbatim.
    capabilities.set(
        listOf(
            mapOf("deviceName" to "Pixel.*", "version" to "14", "platformName" to "Android", "realDevice" to true),
            mapOf("deviceName" to "Galaxy S.*", "version" to "13", "platformName" to "Android")
        )
    )

    // Optional behavior
    waitForResults.set(true)            // poll until the run completes (default true)
    failBuildOnTestFailure.set(true)    // default true
    reportXml.set(layout.buildDirectory.file("testingbot/espresso-junit.xml"))
}

deviceName accepts a regular expression, so "Pixel.*" matches any Pixel and "*" matches any device. Commonly used keys are deviceName, version, platformName ("Android"), realDevice, phoneOnly and tabletOnly. Run ./gradlew testingbotDevices to see what is available on your plan.

4. Tasks

# Upload only
./gradlew testingbotUpload

# Build the APKs first, then run Espresso on TestingBot
./gradlew assembleDebug assembleDebugAndroidTest testingbotEspresso

# Discover device names/versions for your capabilities
./gradlew testingbotDevices

5. Android Gradle Plugin auto-wiring

If the com.android.application plugin is applied, naming a variant lets the plugin fill in the conventional APK paths and depend on the matching assemble tasks automatically.

testingbot {
    autoWireFromVariant.set("debug")   // defaults appApk/testApk + dependsOn assembleDebug(AndroidTest)
    capabilities.set(listOf(mapOf("deviceName" to "Pixel.*", "version" to "14", "platformName" to "Android")))
}

Now ./gradlew testingbotEspresso builds the APKs and runs the tests in one go. Explicitly set appApk / testApk paths always take precedence.

Full DSL reference

Property Type Default Description
key String TESTINGBOT_KEY / testingbot.key API key
secret String TESTINGBOT_SECRET / testingbot.secret API secret
apiBaseUrl String https://api.testingbot.com/v1 API base URL
appApk RegularFile App APK to upload / test
testApk RegularFile Instrumented Espresso test APK
capabilities List<Map<String, Any>> [] One run per entry; passed through verbatim
espressoOptions Map<String, Any> {} Optional run options passed through verbatim
waitForResults Boolean true Poll until the run completes
pollIntervalSeconds Long 15 Seconds between status polls
timeoutMinutes Long 30 Max minutes to wait for results
failBuildOnTestFailure Boolean true Fail the build when a run reports failures
reportXml RegularFile build/testingbot/espresso-junit.xml Where to write the JUnit report
autoWireFromVariant String Optional AGP variant to auto-wire

CI example (GitHub Actions)

- uses: actions/setup-java@v4
  with: { distribution: temurin, java-version: 21 }
- run: ./gradlew assembleDebug assembleDebugAndroidTest testingbotEspresso
  env:
    TESTINGBOT_KEY: ${{ secrets.TESTINGBOT_KEY }}
    TESTINGBOT_SECRET: ${{ secrets.TESTINGBOT_SECRET }}
Was this page helpful?
Last updated