Skip to main content

Mobile UI Testing CLI - Run YAML-based mobile tests anywhere

Project description

mut - Mobile UI Testing CLI

Run YAML-based mobile UI tests anywhere - CI/CD, local development, or scripts.

Features

  • Run anywhere - No Claude Code dependency, works in CI/CD
  • Fast screenshots - ~50ms via scrcpy frame buffer
  • AI verification - Gemini 2.5 Flash for visual assertions
  • Video recording - Capture test execution for debugging
  • Record tests - Capture user interactions with approval UI
  • Conditional actions - Branch based on screen state
  • Verbose logging - Debug-level file logging for troubleshooting

Installation

pip install mut

Requirements

  • Python 3.11+
  • Android device/emulator with USB debugging enabled
  • adb in PATH
  • scrcpy 3.x installed
  • GOOGLE_API_KEY environment variable (for AI features)

Quick Start

Run a test

mut run tests/login.yaml

Record a test

mut record login-flow --app com.example.app
# Interact with your app...
mut stop
# Opens approval UI in browser

List devices

mut devices

YAML Test Format

config:
  app: com.example.app

setup:
  - terminate_app
  - launch_app
  - wait: 2s

tests:
  - name: Login flow
    steps:
      - tap: "Email"
      - type: "user@test.com"
      - tap: "Password"
      - type: "secret123"
      - tap: "Sign In"
      - verify_screen: "Welcome screen with user greeting"

Actions Reference

Basic Actions

Action Description Example
tap Tap element by text or coordinates tap: "Submit" or tap: [540, 1200]
type Type text into focused field type: "hello@example.com"
swipe Swipe gesture swipe: {direction: up, distance: 300}
long_press Long press element long_press: "Item"
back Press back button back
hide_keyboard Dismiss keyboard hide_keyboard

Wait Actions

Action Description Example
wait Wait fixed duration wait: 2s
wait_for Wait for element to appear wait_for: "Loading complete"
scroll_to Scroll until element visible scroll_to: "Terms of Service"

App Lifecycle

Action Description Example
launch_app Launch configured app launch_app
terminate_app Force stop app terminate_app

AI Verification

Action Description Example
verify_screen Assert screen matches description (deferred) verify_screen: "Login form visible"

Conditional Actions

# Execute steps if element is present
- if_present: "Skip Tutorial"
  then:
    - tap: "Skip Tutorial"

# Execute steps if element is absent
- if_absent: "Login Button"
  then:
    - tap: "Sign Up"

# Branch based on screen state (AI-powered)
- if_screen: "2FA prompt shown"
  then:
    - tap: "Skip for now"
  else:
    - tap: "Continue"

Commands

mut run <test.yaml>

Execute a YAML test file.

# Basic execution
mut run tests/login.yaml

# Specify device
mut run tests/login.yaml --device emulator-5554

# Custom output directory
mut run tests/login.yaml --output reports/

# Generate JUnit XML report
mut run tests/login.yaml --junit results.xml

mut record <name>

Start recording user interactions.

mut record checkout-flow --app com.example.shop

mut stop

Stop recording and generate YAML test.

mut stop
# Opens browser with approval UI
# Review and edit steps
# Export YAML when done

mut devices

List connected devices.

mut devices

mut report <dir>

Generate HTML report from JSON results.

mut report tests/reports/2026-01-16_login/

Configuration

Environment Variables

Variable Description
GOOGLE_API_KEY Gemini API key for AI features
MUT_DEVICE Default device ID
MUT_VERBOSE Enable verbose file logging (true/false)

Global config (~/.mut.yaml)

ai:
  model: gemini-2.5-flash

defaults:
  video: true
  verbose: false

Project config (.mut.yaml)

device: emulator-5554
test_dir: tests/
report_dir: reports/
verbose: true

Verbose Logging

Enable debug-level file logging for troubleshooting:

# Via .env file (recommended)
echo "MUT_VERBOSE=true" >> .env

# Via environment variable
MUT_VERBOSE=true mut run tests/login.yaml

Log file locations:

  • Recording: tests/<name>/debug.log
  • Test run: tests/<name>/runs/<timestamp>/debug.log

Logs include: step execution, element search, AI calls, timing, retries.

Recording Workflow

  1. Start recording: mut record my-test --app com.example.app
  2. Interact with app: Touch, type, swipe - all captured with video
  3. Stop recording: mut stop
  4. Review in browser: Approval UI opens automatically
  5. Edit steps: Adjust descriptions, add verifications
  6. Export YAML: Download the generated test file

Recording folder structure:

tests/my-test/
├── video.mp4              # Screen recording
├── video.timestamps.json  # Frame timing data
├── touch_events.json      # Raw touch data
├── analysis.json          # AI step analysis
└── debug.log              # Verbose logs (if enabled)

Test Run Structure

Each test run creates a timestamped folder:

tests/my-test/
├── test.yaml              # Test definition
└── runs/
    └── 2026-01-17_14-30-25/
        └── debug.log      # Run-specific logs

CI/CD Integration

GitHub Actions

name: Mobile UI Tests
on: [push]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install mut
        run: pip install mut

      - name: Run tests
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: 34
          script: mut run tests/login.yaml --junit results.xml
        env:
          GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}

      - name: Upload test results
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: test-results
          path: results.xml

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mutcli-0.3.0.tar.gz (303.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mutcli-0.3.0-py3-none-any.whl (131.3 kB view details)

Uploaded Python 3

File details

Details for the file mutcli-0.3.0.tar.gz.

File metadata

  • Download URL: mutcli-0.3.0.tar.gz
  • Upload date:
  • Size: 303.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for mutcli-0.3.0.tar.gz
Algorithm Hash digest
SHA256 9e3238dbed366e408073aefc70b6eecf582e424708149b747883a1a9451abf81
MD5 e44535b2d00b57b80d25f113f9103a4b
BLAKE2b-256 8ebd4802548148a603d62b6b4223e48a8ec6105c98dbccc4a78dcb99c4a47d0b

See more details on using hashes here.

File details

Details for the file mutcli-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: mutcli-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 131.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for mutcli-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f11cc84aed6b43d022c903c3e0e26863e7ca322a617ac6d8c1b2965524a2d365
MD5 324aaee3bcada3bb43486cf5b2232621
BLAKE2b-256 48e0c6e1cd216379ceec929f02b69c4bfe0fff5e90ccf39cf41ef1e38c2fc861

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page