Real Device Cloud — BrowserStack, Sauce Labs

9 min read

Running tests on your local emulator covers one device, one OS version, and no OEM customisation. In production, your app runs on hundreds of device/OS combinations. Real device clouds bridge that gap: they give you instant access to hundreds of physical devices without owning a single one. This lesson covers how to connect your Appium tests to BrowserStack and Sauce Labs, the two most widely used providers.

Why real device clouds

Coverage without hardware. Running on a Samsung Galaxy S24 with One UI, a Pixel 8 with stock Android, and an iPhone 15 Pro simultaneously — without owning any of them.

No maintenance. Devices are updated, charged, cleaned, and managed by the provider. You never debug a broken USB cable at 2am before a release.

Scale on demand. Run 50 tests in parallel across 50 different devices. No device farm infrastructure to provision.

Pre-configured environments. Providers handle Appium server setup, WebDriverAgent signing for iOS, and ADB connectivity. You just send capabilities and get results.

BrowserStack Automate

BrowserStack provides a hosted Appium server at https://hub-cloud.browserstack.com/wd/hub. Your tests connect to this URL instead of http://127.0.0.1:4723.

Uploading your app

First, upload the APK or IPA to BrowserStack's app storage:

curl -u "username:accessKey" \
  -X POST "https://api-cloud.browserstack.com/app-automate/upload" \
  -F "file=@/path/to/app.apk"

The response contains an app_url like bs://1234abc5678def. Use this as the app capability.

Capabilities for BrowserStack

import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.options.UiAutomator2Options;
 
import java.net.URL;
import java.util.HashMap;
 
public class BrowserStackTest {
 
    public AndroidDriver createAndroidDriver() throws Exception {
        HashMap<String, Object> bstackOptions = new HashMap<>();
        bstackOptions.put("userName", System.getenv("BS_USERNAME"));
        bstackOptions.put("accessKey", System.getenv("BS_ACCESS_KEY"));
        bstackOptions.put("deviceName", "Samsung Galaxy S23");
        bstackOptions.put("osVersion", "13.0");
        bstackOptions.put("projectName", "My Banking App");
        bstackOptions.put("buildName", "Release 2.1.0");
        bstackOptions.put("sessionName", "Login smoke test");
        bstackOptions.put("networkLogs", true);
        bstackOptions.put("deviceLogs", true);
 
        UiAutomator2Options options = new UiAutomator2Options();
        options.setCapability("bstack:options", bstackOptions);
        options.setApp("bs://your-app-hash-from-upload");
 
        return new AndroidDriver(
            new URL("https://hub-cloud.browserstack.com/wd/hub"),
            options
        );
    }
}

Never hardcode credentials — use environment variables (BS_USERNAME, BS_ACCESS_KEY) and inject them in CI.

Finding valid device/version combinations

BrowserStack's Capabilities Builder at https://www.browserstack.com/app-automate/capabilities generates exact capability values. Device names and OS versions are case-sensitive — "Samsung Galaxy S23" is valid; "samsung s23" is not.

Sauce Labs Real Device Cloud

Sauce Labs uses the same W3C capability structure with sauce:options instead of bstack:options.

HashMap<String, Object> sauceOptions = new HashMap<>();
sauceOptions.put("username", System.getenv("SAUCE_USERNAME"));
sauceOptions.put("accessKey", System.getenv("SAUCE_ACCESS_KEY"));
sauceOptions.put("deviceName", "Samsung Galaxy S.*");   // regex matching
sauceOptions.put("platformVersion", "13");
sauceOptions.put("build", "Release 2.1.0");
sauceOptions.put("name", "Login test");
 
UiAutomator2Options options = new UiAutomator2Options();
options.setCapability("sauce:options", sauceOptions);
options.setApp("storage:filename=app.apk");   // if uploaded to Sauce storage
 
AndroidDriver driver = new AndroidDriver(
    new URL("https://ondemand.us-west-1.saucelabs.com/wd/hub"),
    options
);

Sauce Labs supports regex for deviceName, which lets you match a class of devices rather than a specific model. Samsung Galaxy S.* matches any Samsung Galaxy S device.

Abstracting the driver factory

A driver factory handles both local and cloud targets:

public class DriverFactory {
 
    public static AndroidDriver createAndroidDriver(String target) throws Exception {
        UiAutomator2Options options = new UiAutomator2Options();
 
        if ("local".equals(target)) {
            options.setDeviceName("emulator-5554");
            options.setPlatformVersion("14");
            options.setApp("/path/to/local.apk");
            return new AndroidDriver(new URL("http://127.0.0.1:4723"), options);
 
        } else if ("browserstack".equals(target)) {
            HashMap<String, Object> bstackOptions = new HashMap<>();
            bstackOptions.put("userName", System.getenv("BS_USERNAME"));
            bstackOptions.put("accessKey", System.getenv("BS_ACCESS_KEY"));
            bstackOptions.put("deviceName", "Pixel 7");
            bstackOptions.put("osVersion", "13.0");
            options.setCapability("bstack:options", bstackOptions);
            options.setApp("bs://" + System.getenv("BS_APP_ID"));
            return new AndroidDriver(new URL("https://hub-cloud.browserstack.com/wd/hub"), options);
 
        } else {
            throw new IllegalArgumentException("Unknown target: " + target);
        }
    }
}

Switch targets with a Maven property:

mvn test -Dtarget=browserstack

Accessing session recordings

After a cloud test run, BrowserStack and Sauce Labs record:

  • Full session video
  • Device logs (logcat on Android, XCTest runner logs on iOS)
  • Network traffic logs
  • Screenshots at each step (some plans)

Access them via the provider's dashboard or REST API. Both providers also offer an Appium-compatible driver.getVideoUrl() or equivalent after the session ends.

Cost management

Cloud providers charge per device-minute. Practices that reduce cost:

  • Kill sessions in @AfterClass — don't let idle sessions run
  • Set newCommandTimeout — orphaned sessions time out automatically
  • Run locally during development; send to cloud only for pre-release matrix runs
  • Use the free tier or open-source plan for CI on open-source projects (both providers offer this)

AWS Device Farm

AWS Device Farm is a third option that integrates naturally with AWS-native CI/CD (CodePipeline, CodeBuild). It supports Appium with the same capabilities structure. The device catalogue is smaller than BrowserStack or Sauce Labs but is included in AWS billing which some teams prefer for consolidated invoicing.

// tip to track lessons you complete and pick up where you left off across devices.