Starts a TestingBot Tunnel so your tests can reach a local or staging environment.
Description
Starts a TestingBot Tunnel in the background and waits until it is genuinely ready, so the devices in TestingBot's cloud can reach an app that isn't publicly routable — a staging host, a service on the build machine, or anything behind your firewall.
Pair it with the TestingBot Tunnel Stop Step at the end of the Workflow. Bitrise has no post-build hook, so the tunnel has to be shut down by a Step that always runs.
You only need this for Appium and Selenium tests. The Espresso, XCUITest
and Maestro Steps can open their own tunnel with their tunnel input.
- Add your TestingBot key and secret as Bitrise Secrets, and reference
them from the
testingbot_key/testingbot_secretinputs. - Add this Step before the Step that runs your tests.
- Add TestingBot Tunnel Stop as the last Step of the Workflow.
- In your tests, set
tunnelIdentifierinsidetb:optionsto the exported$TESTINGBOT_TUNNEL_IDENTIFIER.
The tunnel is a Java program and needs Java 11 or newer on the Stack. Most
Android Stacks ship a JDK; on a plain macOS Stack you may need an
Install Java Step first.
If the tunnel fails to start, the Step prints the full tunnel log — that log
answers nearly every tunnel question. Raise ready_timeout on a slow network.
Add this step directly to your workflow in the Bitrise Workflow Editor.
You can also run this step directly with Bitrise CLI.
Start the tunnel, run the tests, stop the tunnel — the stop Step is configured to run even if the tests fail:
- testingbot-tunnel:
inputs:
- testingbot_key: $TESTINGBOT_KEY
- testingbot_secret: $TESTINGBOT_SECRET
- script:
title: Run Appium tests
inputs:
- content: |-
#!/usr/bin/env bash
set -eo pipefail
npm test
- testingbot-tunnel-stop: {}In your test capabilities, route the session through the tunnel:
const capabilities = {
platformName: 'Android',
'appium:deviceName': 'Pixel 9',
'appium:app': process.env.TESTINGBOT_APP_URL,
'tb:options': {
tunnelIdentifier: process.env.TESTINGBOT_TUNNEL_IDENTIFIER,
build: `Bitrise #${process.env.BITRISE_BUILD_NUMBER}`,
},
};- script:
title: Start the app under test
inputs:
- content: |-
#!/usr/bin/env bash
npm run start:ci &
sleep 5
- testingbot-tunnel:
inputs:
- testingbot_key: $TESTINGBOT_KEY
- testingbot_secret: $TESTINGBOT_SECRET
- script:
title: Run tests against http://localhost:3000
inputs:
- content: npm test
- testingbot-tunnel-stop: {}The default already keeps concurrent Bitrise builds apart. Set it explicitly when several tunnels run inside one build:
- testingbot-tunnel:
inputs:
- testingbot_key: $TESTINGBOT_KEY
- testingbot_secret: $TESTINGBOT_SECRET
- tunnel_identifier: staging-$BITRISE_BUILD_NUMBER
- ready_timeout: "180"The log is printed automatically when the tunnel fails to start. To see it on a successful run too, raise the level and ask the stop Step to print it:
- testingbot-tunnel:
inputs:
- testingbot_key: $TESTINGBOT_KEY
- testingbot_secret: $TESTINGBOT_SECRET
- log_level: debug
- testingbot-tunnel-stop:
inputs:
- print_log: "true"The Espresso, XCUITest and Maestro Steps open their own tunnel:
- testingbot-espresso:
inputs:
- testingbot_key: $TESTINGBOT_KEY
- testingbot_secret: $TESTINGBOT_SECRET
- device: Pixel 8
- tunnel: "true"Inputs
| Key | Description | Flags | Default |
|---|---|---|---|
testingbot_key |
Your TestingBot API key, from the member area. Store it as a Bitrise Secret and reference it here. | required, sensitive | $TESTINGBOT_KEY |
testingbot_secret |
Your TestingBot API secret, from the member area. Store it as a Bitrise Secret and reference it here. | required, sensitive | $TESTINGBOT_SECRET |
tunnel_identifier |
Names the tunnel so tests can ask for it explicitly, and so several tunnels can run in parallel without colliding. Pass the same value as tunnelIdentifier inside tb:options in your test capabilities. The default keeps concurrent Bitrise builds apart. |
required | bitrise-$BITRISE_BUILD_NUMBER |
ready_timeout |
Maximum seconds to wait for the tunnel to signal that it is ready before failing the Step. The Step watches the tunnel's own ready file rather than its console output, so this is a real readiness check. | required | 120 |
log_level |
The tunnel's log level. The log is printed automatically if the tunnel fails to start; raise this to debug when diagnosing a connection problem. |
required | info |
additional_args |
Appended verbatim to the tunnel command line, for options this Step doesn't expose — for example --fast-fail-regexps, --proxy, --pac or --dns. See the command line reference. |
||
download_url |
The tunnel archive to download. Point this at an internal mirror if your build machines can't reach testingbot.com directly. | required | https://testingbot.com/downloads/testingbot-tunnel.zip |
download_sha256 |
SHA-256 of the tunnel archive. When set, the Step refuses to run a download that doesn't match. Leave empty to skip verification — the download still happens over HTTPS. Set it if you pin a specific tunnel build via download_url. |
Outputs
| Environment Variable | Description |
|---|---|
TESTINGBOT_TUNNEL_IDENTIFIER |
Pass this as tunnelIdentifier inside tb:options in your test capabilities to route the session through this tunnel. |
TESTINGBOT_TUNNEL_PID |
PID of the running tunnel, used by the Tunnel Stop Step. |
TESTINGBOT_TUNNEL_LOG_PATH |
Path to the tunnel's log file. |
TESTINGBOT_TUNNEL_READY_FILE |
The file the tunnel touches once it is ready. |
We welcome pull requests and issues against this repository.
For pull requests, work on your changes in a forked repository and use the Bitrise CLI to run step tests locally.
This Step is developed in the testingbot-bitrise monorepo alongside the other TestingBot Steps, and mirrored into this repository on release. Please open pull requests against the monorepo, not against the mirror — changes pushed here are overwritten on the next release.
The monorepo holds an offline suite that runs every Step against a mock of the TestingBot API, so it needs no credentials:
tests/run.shThe live check lives here, in bitrise.yml. It performs a real upload, so it
needs a TestingBot account:
bitrise run testIt reads TESTINGBOT_KEY, TESTINGBOT_SECRET and SAMPLE_APP_URL — put them in
a git-ignored .bitrise.secrets.yml. SAMPLE_APP_URL must point at a real
.apk or .ipa; TestingBot parses the binary, so a placeholder file is
rejected.
scripts/build.sh --check # shared helpers are in sync (run from the monorepo)
shellcheck -x step.sh
bitrise run audit-this-step
bitrise run generate_readmeREADME.md is generated from step.yml plus the files in docs/ — edit those,
never the README itself.
Open an issue with the Bitrise build log (with credentials redacted) and the Stack you are running on.
Learn more about developing steps: