ScreenshotNeo

BlogHow-to

How to Run Flutter Integration Tests on BrowserStack App Automate

Build and upload the right Flutter test artifacts, launch Android or iOS runs on BrowserStack App Automate, and find results by build ID.

By the ScreenshotNeo team4 October 20268 min read

To run Flutter integration tests on BrowserStack App Automate, build the platform-specific test artifacts, upload them, submit a build request with the returned artifact IDs and supported device names, then inspect the run in App Automate using its build_id.

The artifact flow differs by platform: Android uses an app artifact plus a Flutter test suite APK. iOS uses a Flutter test package ZIP. They have separate upload and build endpoints, so keep their request fields distinct.

1. Prepare credentials and artifacts

You need a BrowserStack username and access key, a Flutter project with integration tests, and a device and OS combination currently supported by App Automate. Get credentials from your BrowserStack account; do not commit them to source control. See BrowserStack’s Flutter getting-started guide and Flutter integration testing overview.

Build the app and test artifacts using the commands appropriate to your Flutter and Gradle/Xcode project. Artifact generation depends on the project’s test setup; follow the current BrowserStack and Flutter project instructions rather than assuming one build command fits every project.

Platform Artifacts to upload Build request fields
Android App (.apk or .aab) and test suite (.apk) app, testSuite, devices
iOS Flutter test package (.zip) testPackage, devices

2. Run Android tests

Upload the app and test suite

Set credentials and artifact paths in your shell. These commands upload local files as multipart form data. Save the app_url and test_suite_url returned by the respective requests; use your own returned values in the build call.

export BROWSERSTACK_USERNAME='YOUR_USERNAME'
export BROWSERSTACK_ACCESS_KEY='YOUR_ACCESS_KEY'
export ANDROID_APP_PATH='./build/app/outputs/flutter-apk/app-release.apk'
export ANDROID_SUITE_PATH='./path/to/flutter-test-suite.apk'

curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \
  -X POST 'https://api-cloud.browserstack.com/app-automate/flutter-integration-tests/v2/android/app' \
  -F "file=@$ANDROID_APP_PATH"

curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \
  -X POST 'https://api-cloud.browserstack.com/app-automate/flutter-integration-tests/v2/android/test-suite' \
  -F "file=@$ANDROID_SUITE_PATH"

Each response contains an identifier for the uploaded artifact. Uploading a changed file creates a new identifier. Always use the latest response values; sample bs:// IDs in documentation are examples, not reusable artifacts. See the official pages for uploading the app and uploading the test suite.

Launch the Android build

Replace the placeholders with the exact IDs from your uploads and a currently supported device identifier, including OS version. Device examples in older documentation may no longer be available.

curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \
  -X POST 'https://api-cloud.browserstack.com/app-automate/flutter-integration-tests/v2/android/build' \
  -H 'Content-Type: application/json' \
  -d '{"app":"<uploaded-app-url>","testSuite":"<uploaded-test-suite-url>","devices":["<supported-device>-<os-version>"]}'

A successful response includes a build_id. Record it so you can identify the run in the App Automate dashboard. You can request multiple devices by adding supported device identifiers to the devices array.

3. Run iOS tests

For iOS, upload the Flutter test package as a ZIP to the iOS test-package endpoint. This is a different artifact flow from Android; do not pass Android’s app and testSuite fields.

export IOS_PACKAGE_PATH='./path/to/flutter-ios-test-package.zip'

curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \
  -X POST 'https://api-cloud.browserstack.com/app-automate/flutter-integration-tests/v2/ios/test-package' \
  -F "file=@$IOS_PACKAGE_PATH"

Use the returned test package identifier to start the run:

curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \
  -X POST 'https://api-cloud.browserstack.com/app-automate/flutter-integration-tests/v2/ios/build' \
  -H 'Content-Type: application/json' \
  -d '{"testPackage":"<uploaded-test-package-url>","devices":["<supported-device>-<os-version>"]}'

As with Android, the response includes a build_id. Choose currently supported iOS device and OS combinations, and use multiple device identifiers in the array when you need broader coverage. See BrowserStack’s Flutter execution guide.

4. Use Python or Node.js for the API calls

The following examples launch a build after you have uploaded artifacts. Set the credentials and artifact IDs from your upload responses in environment variables. Choose the platform-specific endpoint and payload. They print the API response, including the build ID when the request succeeds.

Python

import json
import os
import requests

username = os.environ["BROWSERSTACK_USERNAME"]
access_key = os.environ["BROWSERSTACK_ACCESS_KEY"]
platform = os.environ.get("PLATFORM", "android")

if platform == "android":
    endpoint = "https://api-cloud.browserstack.com/app-automate/flutter-integration-tests/v2/android/build"
    payload = {
        "app": os.environ["ANDROID_APP_URL"],
        "testSuite": os.environ["ANDROID_TEST_SUITE_URL"],
        "devices": ["<supported-device>-<os-version>"],
    }
elif platform == "ios":
    endpoint = "https://api-cloud.browserstack.com/app-automate/flutter-integration-tests/v2/ios/build"
    payload = {
        "testPackage": os.environ["IOS_TEST_PACKAGE_URL"],
        "devices": ["<supported-device>-<os-version>"],
    }
else:
    raise ValueError("PLATFORM must be android or ios")

response = requests.post(
    endpoint,
    auth=(username, access_key),
    headers={"Content-Type": "application/json"},
    data=json.dumps(payload),
    timeout=90,
)
response.raise_for_status()
print(response.json())

Node.js

const username = process.env.BROWSERSTACK_USERNAME;
const accessKey = process.env.BROWSERSTACK_ACCESS_KEY;
const platform = process.env.PLATFORM || 'android';

if (!username || !accessKey) throw new Error('Set BrowserStack credentials');

let endpoint;
let payload;
if (platform === 'android') {
  endpoint = 'https://api-cloud.browserstack.com/app-automate/flutter-integration-tests/v2/android/build';
  payload = {
    app: process.env.ANDROID_APP_URL,
    testSuite: process.env.ANDROID_TEST_SUITE_URL,
    devices: ['<supported-device>-<os-version>'],
  };
} else if (platform === 'ios') {
  endpoint = 'https://api-cloud.browserstack.com/app-automate/flutter-integration-tests/v2/ios/build';
  payload = {
    testPackage: process.env.IOS_TEST_PACKAGE_URL,
    devices: ['<supported-device>-<os-version>'],
  };
} else {
  throw new Error('PLATFORM must be android or ios');
}

const auth = Buffer.from(`${username}:${accessKey}`).toString('base64');
const response = await fetch(endpoint, {
  method: 'POST',
  headers: {
    Authorization: `Basic ${auth}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(payload),
});
const body = await response.text();
if (!response.ok) throw new Error(`BrowserStack ${response.status}: ${body}`);
console.log(body);

5. Inspect results and debug failures

Open App Automate and locate the build using its returned ID. BrowserStack describes text, console, video, and network logs as debugging information available through its dashboard or API. Availability can depend on the run and configuration; consult the run details rather than assuming every log is enabled for every build. The execution guide covers the workflow.

Options and operational choices

  • Device coverage: choose device and OS combinations from the current supported-device documentation. Multiple devices are accepted in devices; wider matrices increase coverage and consume more execution capacity.
  • Artifact upload: upload local artifacts through the documented endpoints. BrowserStack also describes public URL upload options on its product pages; use the current API documentation for the exact request format.
  • Artifact limits: the app upload page states a 1 GB limit. Limits can change, so verify the current upload guidance before relying on it.
  • Repeatability: retain upload responses with the build metadata in CI. Treat each upload as a distinct artifact, particularly after rebuilding the app or test suite.

Troubleshooting

Symptom Likely cause Fix
Authentication failure Missing, mistyped, or incorrectly paired username and access key. Check the account credentials and ensure the request uses HTTP basic authentication. Keep secrets in CI secret storage.
Upload fails Wrong file path, unsupported artifact type, upload size limit, or network interruption. Confirm the file exists and matches the platform’s required format. Check the current upload documentation for size and format constraints, then retry.
Build request rejects an artifact A placeholder, stale ID, or ID from the wrong upload was supplied. Copy the latest identifier returned by the corresponding upload. Android needs app and test-suite IDs; iOS needs the test-package ID.
Device is unavailable or rejected Device name or OS version is not a currently supported combination. Choose an exact current combination from BrowserStack’s device catalog; do not assume an old example remains valid.
Run starts the wrong app version The build request still points to an earlier app upload. After uploading a changed app, replace the app ID in the build payload and retain the new ID alongside the build.
Build is accepted but tests fail Failure may be in app behavior, test setup, or a platform-specific artifact. Inspect the build’s available text, console, video, and network logs. Confirm the test suite/package was built for the intended platform and corresponds to the app.
Request times out locally The client stopped waiting or a network connection interrupted the request. Use a suitable client timeout, preserve the response when received, and check App Automate for the build before submitting duplicates.

Performance, reliability, and cost

Run a small device set while iterating, then expand the device array for release coverage. Parallel device runs can provide wider coverage but require more execution capacity. Upload artifacts once per build and reuse their returned IDs for the intended run; re-upload only when the artifact changes. Preserve build IDs and upload responses in CI logs so failures can be traced to exact inputs.

BrowserStack credentials and device availability are external dependencies. Keep credentials in a secret manager, avoid logging access keys, and handle non-success HTTP responses explicitly. Check your BrowserStack plan and current product terms for pricing and run limits; the workflow references here do not establish a price.

Or skip the browser setup

BrowserStack App Automate is the cloud device workflow for running Flutter app tests. If the task alongside testing is capturing website screenshots for reports or documentation, ScreenshotNeo can return an image or PDF with one GET request; it does not run Flutter tests.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation. ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.

Sign up free for 1,000 screenshots a month, with no card required.

FAQ

Can I use the same build payload for Android and iOS?

No. Android uses app and testSuite; iOS uses testPackage. Use each platform’s upload and build endpoints.

Can I reuse an artifact ID after uploading a new build?

No. A new upload returns a distinct identifier. Update the build request to point at the newest artifact you intend to test.

Where do I get a valid device identifier?

Use the current BrowserStack supported-device documentation and select a valid device and OS combination for the platform.

Does a successful API response mean every test passed?

No. The response confirms the build request was accepted and provides a build ID. Inspect the run in App Automate to see the test outcome and available debugging details.