Skip to main content
The patrol build command creates optimized test binaries for Android, iOS, and macOS. It’s primarily used for CI/CD pipelines and device farms where you need to build once and run tests later.

Synopsis

patrol build <platform> [options]
Where <platform> is one of:
  • android - Build for Android devices and emulators
  • ios - Build for iOS devices and simulators
  • macos - Build for macOS desktop

Description

patrol build performs all the same build steps as patrol test, but stops before running the tests. This is useful when:
  • Running tests on CI/CD platforms like Firebase Test Lab
  • Building once and running tests multiple times
  • Separating build and test stages in your pipeline
  • Testing on device farms that require pre-built binaries
For patrol build to work, you must complete the native setup.

Basic Usage

Build for Android

patrol build android
Outputs:
  • App APK: build/app/outputs/apk/debug/app-debug.apk
  • Test APK: build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk

Build for iOS

patrol build ios
Outputs:
  • App bundle: build/ios_integ/Build/Products/Debug-iphonesimulator/Runner.app
  • Test runner: build/ios_integ/Build/Products/Debug-iphonesimulator/RunnerUITests-Runner.app

Build for macOS

patrol build macos

Build Modes

By default, builds are in debug mode. You can specify a different mode:
--debug
flag
default:"true"
Build in debug mode (default).
patrol build android --debug
patrol build ios --debug
--profile
flag
Build in profile mode for performance testing.
patrol build android --profile
patrol build ios --profile
--release
flag
Build in release mode. Required for physical iOS devices on device farms.
patrol build android --release
patrol build ios --release
To run tests on physical iOS devices on device farms, apps must be built in release mode using --release.

Target Selection

--target
string
default:"all tests"
Specify which test file(s) to include in the build.
patrol build android --target patrol_test/login_test.dart
patrol build ios --target patrol_test/app_test.dart
--exclude
string
Exclude specific test files.
patrol build android --exclude patrol_test/flaky_test.dart
By default, all test files in patrol_test/ are bundled into a single binary.

Flavors

--flavor
string
Build a specific flavor of your app.
patrol build android --flavor staging
patrol build ios --flavor production --release

Build Versioning

--build-name
string
Set the version name (e.g., “1.2.3”).
patrol build android --build-name 1.2.3
patrol build ios --build-name 1.2.3
--build-number
string
Set the version code (e.g., “123”).
patrol build android --build-number 123
patrol build ios --build-number 123

Dart Defines

--dart-define
string
Pass environment variables to your app.
patrol build android --dart-define API_URL=https://api.example.com
--dart-define-from-file
string
Load environment variables from a file.
patrol build android --dart-define-from-file config/prod.json

Tags

--tags
string
Include only tests with specific tags.
patrol build android --tags "smoke"
patrol build ios --tags "smoke && !flaky"
--exclude-tags
string
Exclude tests with specific tags.
patrol build android --exclude-tags "slow"

Platform-Specific Options

Android

--package-name
string
Override the Android package name.
patrol build android --package-name com.example.myapp

iOS

--bundle-id
string
Override the iOS bundle identifier.
patrol build ios --bundle-id com.example.MyApp
--full-isolation
flag
Enable full isolation between test runs on iOS Simulator.
patrol build ios --full-isolation

Advanced Options

--label
flag
default:"true"
Display label overlay on the app during testing.
patrol build android --no-label
--test-server-port
number
default:"8081"
Port for the test instrumentation server.
patrol build android --test-server-port 9001
--app-server-port
number
default:"8082"
Port for the app under test server.
patrol build android --app-server-port 9002
--check-compatibility
flag
default:"true"
Verify dependency compatibility.
patrol build android --no-check-compatibility
--generate-bundle
flag
default:"true"
Generate test bundle file.
patrol build android --no-generate-bundle
--no-tree-shake-icons
flag
Disable icon tree shaking during build.
patrol build android --no-tree-shake-icons
--uninstall
flag
default:"true"
Controls whether to uninstall during subsequent test runs.
patrol build android --no-uninstall

Examples

# Build all tests for Android in debug mode
patrol build android

# Build specific test
patrol build android --target patrol_test/login_test.dart

CI/CD Usage

Here’s how to use patrol build in common CI/CD scenarios:

Firebase Test Lab (Android)

1

Build APKs

patrol build android --release
2

Upload to Firebase Test Lab

gcloud firebase test android run \
  --type instrumentation \
  --app build/app/outputs/apk/release/app-release.apk \
  --test build/app/outputs/apk/androidTest/release/app-release-androidTest.apk \
  --device model=Pixel2,version=30

AWS Device Farm (iOS)

1

Build for release

patrol build ios --release
2

Create IPA files

Package the built apps into IPA files for upload.
3

Upload to Device Farm

Use AWS CLI or console to upload and run tests.

GitHub Actions Example

name: Build Test Binaries
on: [push]

jobs:
  build-android:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: subosito/flutter-action@v2
      
      - name: Install Patrol CLI
        run: dart pub global activate patrol_cli
        
      - name: Build Android APKs
        run: patrol build android --release
        
      - name: Upload APKs
        uses: actions/upload-artifact@v3
        with:
          name: android-apks
          path: |
            build/app/outputs/apk/release/*.apk
            build/app/outputs/apk/androidTest/release/*.apk

  build-ios:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v3
      - uses: subosito/flutter-action@v2
      
      - name: Install Patrol CLI
        run: dart pub global activate patrol_cli
        
      - name: Build iOS Apps
        run: patrol build ios --release
        
      - name: Upload iOS Apps
        uses: actions/upload-artifact@v3
        with:
          name: ios-apps
          path: build/ios_integ/Build/Products/**/*.app

Output Files

Android

After building for Android, you’ll find: Debug mode:
  • build/app/outputs/apk/debug/app-debug.apk (app under test)
  • build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk (test instrumentation)
Release mode:
  • build/app/outputs/apk/release/app-release.apk
  • build/app/outputs/apk/androidTest/release/app-release-androidTest.apk
With flavor:
  • build/app/outputs/apk/{flavor}/debug/app-{flavor}-debug.apk
  • build/app/outputs/apk/androidTest/{flavor}/debug/app-{flavor}-debug-androidTest.apk

iOS

After building for iOS, you’ll find: Simulator:
  • build/ios_integ/Build/Products/Debug-iphonesimulator/Runner.app
  • build/ios_integ/Build/Products/Debug-iphonesimulator/RunnerUITests-Runner.app
Device:
  • build/ios_integ/Build/Products/Release-iphoneos/Runner.app
  • build/ios_integ/Build/Products/Release-iphoneos/RunnerUITests-Runner.app

Under the Hood

The patrol build command uses advanced test bundling:
  1. Discovers tests - Finds all *_test.dart files in patrol_test/
  2. Creates bundle - Generates a single test file that references all tests
  3. Builds binaries - Compiles app and test instrumentation into single binaries
  4. Enables sharding - Each test runs as a separate process for better isolation
This approach provides:
  • Single build for all tests (much faster)
  • Better isolation between test runs
  • Sharding support for parallel execution
  • Native integration with platform test runners
For more details, read the in-depth technical article.

Troubleshooting

Build fails with “Native setup incomplete”

Ensure you’ve completed the native setup guide.

APKs not found after build

Check the exact output path. It varies based on:
  • Build mode (debug/release)
  • Flavor (if specified)
Run with verbose logging to see exact paths:
patrol build android --verbose

iOS build fails on CI

Ensure:
  • You’re running on macOS
  • Xcode is properly installed
  • Code signing is configured for release builds

Version conflicts

Run compatibility check:
patrol build android --check-compatibility

Build docs developers (and LLMs) love