EmuLabZip logo EmuLabZip

CI mode

Last updated · Edit this page on GitHub

emulabzip ci records a session around any command, usually a test run, and then exits with the command's own exit code, so your pipeline behaves as it did, with a recording to look at when something goes wrong.

emulabzip ci -o run.ezsession --app com.example.app -- ./gradlew connectedCheck

It starts recording, runs the command (its output goes through unchanged), stops, writes the session, and prints a one-line result.

Option
-o, --output FILEWhere to write the session (required)
-a, --app IDThe app: samples are taken for it and crashes are limited to it
--networkRecord the HTTP(S) traffic: the device is pointed at the proxy for the run
--screens NA screenshot every N seconds
--fail-on-crashFail the run (exit 1) when the app crashed while it ran, even if the command passed
--summary FILEAlso write the report, in Markdown, to this file
--config FILELimits to hold the run to (default: ./emulabzip.toml, when there is one). See Budgets
--baseline FILEAn earlier session to compare with
--fail-on-regressionFail when a number got worse than the baseline by more than the tolerance
--video [N]Record the screen, in pieces of N seconds (default 30). See Timeline and screen video
--tapsRecord touches (Android)
--replay FILEAnswer the app's requests from a HAR file or a session, so the run does not depend on any server. Needs --network. See Replaying a recording
--passthroughWith --replay: let requests that are not in the recording reach the real server
--fail-on-missWith --replay: fail the run when the app asked for something the recording does not hold
--size BUILDHold an APK, AAB or IPA to the [size] limits of emulabzip.toml. Read before the run. See Build size
--size-baseline BUILDWith --size: an earlier build, to measure growth against
--fail-on-security LEVELAudit the app's security and privacy after the command (needs --app; the proxy's requests are included) and fail on a finding at least this serious: note, warning or error. See Security audit
--visual NAMECompare the screen after the command with a baseline. See Visual regression
--fail-on-visualWith --visual: fail the run when the screen differs more than the limit

The exit code is the command's. If the command passed but --fail-on-crash found a crash, a budget is broken or a regression was asked to fail the run, it is 1; if you press Ctrl+C, it is 130.

When the GITHUB_STEP_SUMMARY environment variable is set (GitHub Actions), the Markdown report is appended to it and shows on the run's page without extra steps.

GitHub Actions#

name: UI tests
on: [pull_request]

jobs:
  android:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with: { distribution: temurin, java-version: 17 }
      - name: Install EmuLabZip
        run: cargo install --git https://github.com/LuisPeixoto/EmuLabZip emulabzip-cli
      - uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: 34
          arch: x86_64
          script: >
            emulabzip ci -o run.ezsession --app com.example.app --fail-on-crash --screens 10
            -- ./gradlew connectedCheck
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: session
          path: run.ezsession

Download the artifact and open it in Sessions → Open…, or read it with emulabzip session show.

You can also gate on accessibility in the same job, after the app is on the screen it should be checked on:

emulabzip a11y --fail-on error

Notes#

  • The emulator must be running before ci starts; with more than one device, pass --device.
  • A session file that already exists is never overwritten.
  • If --network is used, the device must trust the EmuLabZip certificate (see Network). On CI run emulabzip ca install once, on a rootable image.