Back to All Articles
Automation

Cloud Device Testing — AWS Device Farm, Sauce Labs & LambdaTest

Honnesh Muppala May 5, 2026 14 min read

Why Cloud Device Testing?

In 2015, a mid-sized app team might test on a handful of physical devices purchased for the QA lab — a few iPhones, a few Android devices, maybe a tablet. By 2025, the Android ecosystem alone has thousands of unique device and OS version combinations in active use worldwide. No device lab can match that coverage. Cloud device testing platforms solve this problem by giving QA teams on-demand access to thousands of real and virtual devices, all managed, maintained, and accessible via API.

The real cost of an in-house device lab

The economics of physical device labs are rarely examined carefully. Each device costs between $200 and $1,200 to purchase. Devices require OS updates, storage management, and replacement cycles. USB hubs, cables, and charging infrastructure add up. Devices become obsolete as new iOS and Android versions drop support. A lab of 50 devices — barely covering major form factors — might cost $50,000 upfront and $15,000 per year to maintain. A cloud platform with the same or greater coverage costs a fraction of that, billed only for actual test execution time.

Beyond cost, cloud platforms provide video recording of every test run, performance metrics, logs, and screenshots — all automatically captured and accessible from a browser. Debugging a test failure is as simple as watching the recorded video alongside the test logs.

From Amazon: At Amazon, cloud device testing was not optional — it was built into the standard QA workflow for every Fire OS application. Using AWS Device Farm meant we could run our Appium regression suite across 20 real Fire TV devices and 15 Android tablets simultaneously, completing a run that would have taken eight hours on a local lab in under forty minutes. The infrastructure cost was a fraction of what the equivalent physical lab would have required, and the video evidence for every failure dramatically reduced investigation time.

Cloud Testing Architecture

Test Code
(Appium / XCUITest / Selenium)
Cloud Platform API
(Device Farm / Sauce Labs / LambdaTest)
Device Pool
(Selection: OS, device model, form factor)
Real Device
(Samsung, Pixel, iPhone)
Virtual Device
(Emulator / Simulator)
Test Execution
(Parallel across selected devices)
Report Dashboard
(Video, logs, screenshots, performance)

Test code runs locally or in CI — the cloud platform handles device provisioning and execution

AWS Device Farm Overview

AWS Device Farm is Amazon's cloud testing service for mobile and web applications. It is natively integrated with the AWS ecosystem, making it the natural choice for teams already using AWS infrastructure.

Key capabilities

Setting up a Device Farm project via AWS Console

  1. Navigate to AWS Device Farm in the AWS Console.
  2. Create a new project (e.g., "MyApp Mobile Tests").
  3. Create a device pool: select specific devices or create a rule-based pool (e.g., all Android phones with OS 12+).
  4. Upload your app file (.apk for Android, .ipa for iOS) as an upload of type "Android App" or "iOS App."
  5. Upload your test package as a .zip file containing your test code and dependencies.
  6. Schedule a run: select app upload, test package upload, device pool, and timeout settings.

AWS Device Farm with Python Appium

When running Appium tests on Device Farm, the endpoint URL and app capability use Device Farm-specific formats:

from appium import webdriver

# Device Farm Appium endpoint (region-specific)
DEVICE_FARM_ENDPOINT = (
    "https://devicefarm.us-west-2.amazonaws.com/wd/hub"
)

desired_capabilities = {
    "platformName": "Android",
    "appium:automationName": "UIAutomator2",
    "appium:deviceName": "Google Pixel 7",
    # App is referenced by S3 ARN after upload to Device Farm
    "appium:app": "arn:aws:devicefarm:us-west-2:123456789:upload:"
                  "project-arn/app-upload-arn",
    "appium:newCommandTimeout": 90,

    # Device Farm-specific: enable performance data collection
    "appium:deviceFarmPerformanceData": True
}

driver = webdriver.Remote(
    command_executor=DEVICE_FARM_ENDPOINT,
    desired_capabilities=desired_capabilities
)

try:
    # Your test code here
    driver.find_element("id", "com.example.app:id/loginBtn").click()
    # ...
finally:
    driver.quit()

Test package structure for Device Farm

# Device Farm expects a specific zip structure for Appium Python tests
test-package.zip
├── tests/
│   ├── test_login.py
│   ├── test_checkout.py
│   └── conftest.py
├── requirements.txt
└── setup.py  # (or pytest.ini)

# Create the zip:
zip -r test-package.zip tests/ requirements.txt setup.py

AWS Device Farm CLI

The AWS CLI enables fully automated Device Farm test runs — perfect for CI/CD integration:

# 1. Create an upload slot for your app
aws devicefarm create-upload \
  --project-arn arn:aws:devicefarm:us-west-2:123456789:project:abc123 \
  --name "MyApp.apk" \
  --type ANDROID_APP \
  --query 'upload.{arn:arn,url:url}' \
  --output json

# 2. Upload the actual file to the pre-signed S3 URL returned above
curl -T MyApp.apk "PRE_SIGNED_S3_URL_FROM_ABOVE"

# 3. Wait for upload to be processed (SUCCEEDED status)
aws devicefarm get-upload \
  --arn arn:aws:devicefarm:...:upload:UPLOAD_ARN \
  --query 'upload.status'

# 4. Schedule a test run
aws devicefarm schedule-run \
  --project-arn arn:aws:devicefarm:...:project:PROJECT_ARN \
  --app-arn arn:aws:devicefarm:...:upload:APP_UPLOAD_ARN \
  --device-pool-arn arn:aws:devicefarm:...:devicepool:POOL_ARN \
  --name "Regression Run $(date +%Y%m%d-%H%M%S)" \
  --test type=APPIUM_PYTHON,testPackageArn=TEST_PKG_ARN \
  --query 'run.arn' --output text

# 5. Poll for run completion
aws devicefarm get-run \
  --arn arn:aws:devicefarm:...:run:RUN_ARN \
  --query 'run.{status:status,result:result}'

Sauce Labs

Sauce Labs is one of the most established cloud testing platforms, offering both Real Device Cloud and Virtual Cloud (emulators and simulators). It is vendor-neutral and works with any Appium, Selenium, or XCUITest framework.

Key features

Sauce Labs Python Example

from appium import webdriver
import os

# Read credentials from environment variables — never hardcode
SAUCE_USERNAME = os.environ["SAUCE_USERNAME"]
SAUCE_ACCESS_KEY = os.environ["SAUCE_ACCESS_KEY"]

SAUCE_ENDPOINT = (
    f"https://ondemand.us-west-1.saucelabs.com:443/wd/hub"
)

desired_capabilities = {
    "platformName": "Android",
    "appium:automationName": "UIAutomator2",
    "appium:deviceName": "Samsung Galaxy S24",
    "appium:platformVersion": "14",
    "appium:app": "storage:filename=MyApp.apk",  # uploaded via Sauce Storage API

    # Sauce Labs specific options
    "sauce:options": {
        "username": SAUCE_USERNAME,
        "accessKey": SAUCE_ACCESS_KEY,
        "name": "Login Regression Suite",
        "build": f"build-{os.environ.get('GITHUB_RUN_NUMBER', 'local')}",
        "tags": ["regression", "android", "login"],
        "appiumVersion": "2.0.0",
        "recordVideo": True,
        "recordScreenshots": True,
        "extendedDebugging": True,  # captures network HAR + JS console
    }
}

driver = webdriver.Remote(
    command_executor=SAUCE_ENDPOINT,
    desired_capabilities=desired_capabilities
)

try:
    # Mark test result in Sauce Labs dashboard
    driver.execute_script("sauce:job-result=passed")
except Exception as e:
    driver.execute_script("sauce:job-result=failed")
    raise
finally:
    driver.quit()
From Viasat: At Viasat, we used Sauce Labs for cross-browser web testing alongside mobile testing. One of the most valuable features was Sauce Connect — our staging environment was on an internal network, and Sauce Connect let real Sauce Labs devices reach it without any public exposure. Setting up the tunnel took about 30 minutes, but it unlocked testing on real iOS and Android devices against our private staging environment without any firewall changes. For any team whose test environment is not publicly accessible, Sauce Connect is essentially mandatory.

LambdaTest

LambdaTest has grown rapidly and is now a serious competitor to Sauce Labs and BrowserStack, particularly on cost and innovative features. It covers both web and mobile testing.

LambdaTest key offerings

LambdaTest Python Appium capabilities

from appium import webdriver
import os

LT_USERNAME = os.environ["LT_USERNAME"]
LT_ACCESS_KEY = os.environ["LT_ACCESS_KEY"]

LT_ENDPOINT = (
    f"https://{LT_USERNAME}:{LT_ACCESS_KEY}"
    "@mobile-hub.lambdatest.com/wd/hub"
)

desired_capabilities = {
    "platformName": "iOS",
    "appium:automationName": "XCUITest",
    "appium:deviceName": "iPhone 15 Pro",
    "appium:platformVersion": "17",
    "appium:app": "lt://APP_ID_FROM_LT_UPLOAD",

    "lt:options": {
        "username": LT_USERNAME,
        "accessKey": LT_ACCESS_KEY,
        "project": "MyApp iOS Tests",
        "build": "v2.5.0",
        "name": "Login Flow Test",
        "isRealMobile": True,
        "video": True,
        "visual": True,  # enables smart UI screenshots
        "devicelog": True,
        "network": True,  # captures network logs
    }
}

LambdaTest Tunnel for Private Apps

Like Sauce Connect, LambdaTest Tunnel enables devices on the LambdaTest cloud to access your private staging environment:

# Download LambdaTest Tunnel binary
wget https://downloads.lambdatest.com/tunnel/v3/linux/64bit/LT

# Start the tunnel
./LT \
  --user YOUR_LT_USERNAME \
  --key YOUR_LT_ACCESS_KEY \
  --tunnel-name "staging-tunnel"

# Verify tunnel is active in LambdaTest dashboard under Tunnel section
# Then point your test capabilities to your internal staging URL
# e.g., "app": "http://192.168.1.100:3000"

Parallel Testing on Cloud Platforms

The defining advantage of cloud testing is parallelism. Running the same test suite on five devices simultaneously cuts execution time by approximately 80%.

import pytest
from appium import webdriver

# Device matrix — each set of capabilities is a parallel test run
DEVICE_MATRIX = [
    {
        "platformName": "Android",
        "appium:deviceName": "Samsung Galaxy S24",
        "appium:platformVersion": "14",
        "sauce:options": {"name": "Login - Galaxy S24"}
    },
    {
        "platformName": "Android",
        "appium:deviceName": "Google Pixel 8",
        "appium:platformVersion": "14",
        "sauce:options": {"name": "Login - Pixel 8"}
    },
    {
        "platformName": "iOS",
        "appium:deviceName": "iPhone 15 Pro",
        "appium:platformVersion": "17",
        "sauce:options": {"name": "Login - iPhone 15 Pro"}
    },
]

@pytest.mark.parametrize("capabilities", DEVICE_MATRIX)
def test_login_across_devices(capabilities):
    """Run the same login test on all devices in the matrix in parallel."""
    base_caps = {
        "appium:app": "storage:filename=MyApp.apk",
        "sauce:options": {
            "username": SAUCE_USERNAME,
            "accessKey": SAUCE_ACCESS_KEY,
            "build": BUILD_NUMBER,
        }
    }
    caps = {**base_caps, **capabilities}

    driver = webdriver.Remote(SAUCE_ENDPOINT, desired_capabilities=caps)
    try:
        # Test logic here — same test, different device
        login_page = LoginPage(driver)
        login_page.login("testuser@example.com", "TestPassword123!")
        assert login_page.dashboard_is_visible()
        driver.execute_script("sauce:job-result=passed")
    except Exception:
        driver.execute_script("sauce:job-result=failed")
        raise
    finally:
        driver.quit()

# Run with: pytest tests/ -n 3  (3 parallel workers via pytest-xdist)

Real Device vs Virtual Device

Choosing between real and virtual devices is a practical cost-speed-coverage trade-off, not a philosophical one.

Scenario Use Real Device Use Virtual Device
Camera / scanner features Yes — camera hardware required No — no physical camera
Biometric auth (Face ID / fingerprint) Yes — requires real sensor No (limited simulation available)
Push notifications Yes — APNS/FCM to real device Partially (emulators support FCM)
GPS / location Yes — real GPS chip Yes — both support mocked locations
Performance / battery testing Yes — real CPU, memory, thermal No — not representative
Early-stage functional smoke tests Overkill Yes — faster, cheaper
Pre-release regression suite Yes — validate on real hardware Yes — supplement real devices
Cost per minute Higher ($0.17–0.50/min) Lower ($0.05–0.15/min)

Cost and Pricing Models

Cloud testing pricing varies significantly by platform, tier, and usage pattern. The three main models are:

CI Integration with GitHub Actions

# .github/workflows/cloud-tests.yml
name: Cloud Device Tests

on:
  push:
    branches: [main]

jobs:
  sauce-labs-tests:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        platform: [android, ios]

    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install dependencies
        run: pip install -r requirements.txt

      - name: Upload app to Sauce Labs storage
        run: |
          curl -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" \
            -X POST "https://api.us-west-1.saucelabs.com/v1/storage/upload" \
            -H "Content-Type: multipart/form-data" \
            -F "payload=@./builds/MyApp-${{ matrix.platform }}.apk"
        env:
          SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
          SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}

      - name: Run tests on Sauce Labs
        run: pytest tests/${{ matrix.platform }}/ -n 3 --tb=short
        env:
          SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
          SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
          BUILD_NUMBER: ${{ github.run_number }}

Platform Comparison: AWS Device Farm vs BrowserStack vs Sauce Labs vs LambdaTest

Feature AWS Device Farm BrowserStack Sauce Labs LambdaTest
Real Devices Yes (2,000+ incl. Fire OS) Yes (3,500+) Yes (2,000+) Yes (3,000+)
Emulators / Simulators Yes Yes Yes Yes
Appium Support Yes (v1 and v2) Yes Yes Yes
Web Testing Yes (Desktop Web) Yes (excellent) Yes Yes
CI/CD Integration Native AWS (CodePipeline) Excellent — all major CI Excellent — all major CI Excellent — HyperExecute
Private Network Tunnel Yes (AWS VPC) Yes (BrowserStack Local) Yes (Sauce Connect) Yes (LT Tunnel)
Pricing Model Per device-minute Per concurrent session Per concurrent session Per concurrent session
Free Tier 1,000 min/month 100 min/month Trial only Yes (limited)
Best For AWS-native teams, Fire OS Broadest device coverage, web Enterprise, extended debugging Cost-conscious teams, visual testing

Best Practices for Cloud Device Testing


Back to Blog
From Experience — Virtusa: Leading a team of 270 testers at Virtusa, we standardised on Appium for real Android device testing and Selenium WebDriver for web regression. The biggest challenge wasn't the tooling — it was consistency across a team that size. We enforced a strict Page Object Model convention and a pre-merge locator review checklist. Within two sprints, flaky test rates dropped significantly and the team achieved a 20% efficiency gain across regression cycles. At that scale, test architecture decisions matter far more than individual test quality.