android-ci-tests

Setup GitHub Actions workflow for running Android tests in CI

16 stars

Best use case

android-ci-tests is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Setup GitHub Actions workflow for running Android tests in CI

Teams using android-ci-tests should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/android-ci-tests/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/devops/android-ci-tests/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/android-ci-tests/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How android-ci-tests Compares

Feature / Agentandroid-ci-testsStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Setup GitHub Actions workflow for running Android tests in CI

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Android CI Tests Setup

Sets up GitHub Actions workflow for running Android unit and instrumented tests in CI.

## Prerequisites

- Android project with test dependencies
- GitHub repository

## Inputs

| Input | Required | Default | Description |
|-------|----------|---------|-------------|
| project_path | Yes | . | Android project root |

## Process

### Step 1: Create CI Test Workflow

Create `.github/workflows/test.yml`:

```yaml
name: Android CI Tests

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  unit-tests:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2

      - name: Set up JDK 17
        uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00  # v4.7.0
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Setup Gradle cache
        uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57  # v4.2.0
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
            .gradle/configuration-cache
          key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
          restore-keys: |
            gradle-${{ runner.os }}-

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v4

      - name: Run unit tests
        run: ./gradlew test --stacktrace

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4.6.0
        with:
          name: unit-test-results
          path: |
            app/build/test-results/
            app/build/reports/tests/
          retention-days: 7

      - name: Upload coverage reports (if JaCoCo configured)
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4.6.0
        with:
          name: coverage-reports
          path: app/build/reports/jacoco/
          retention-days: 7

  lint:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2

      - name: Set up JDK 17
        uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00  # v4.7.0
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Setup Gradle cache
        uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57  # v4.2.0
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
            .gradle/configuration-cache
          key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
          restore-keys: |
            gradle-${{ runner.os }}-

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v4

      - name: Run lint
        run: ./gradlew lintDebug --stacktrace

      - name: Upload lint results
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4.6.0
        with:
          name: lint-results
          path: app/build/reports/lint-results-debug.html
          retention-days: 7

  instrumented-tests:
    runs-on: ubuntu-latest
    # Optional: Only run instrumented tests if unit tests pass
    needs: unit-tests

    steps:
      - name: Checkout code
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683  # v4.2.2

      - name: Set up JDK 17
        uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00  # v4.7.0
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Setup Gradle cache
        uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57  # v4.2.0
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
            .gradle/configuration-cache
          key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
          restore-keys: |
            gradle-${{ runner.os }}-

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v4

      - name: Enable KVM group permissions
        run: |
          echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
          sudo udevadm control --reload-rules
          sudo udevadm trigger --name-match=kvm

      - name: Setup Android SDK
        uses: android-actions/setup-android@v3

      - name: AVD cache
        uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57  # v4.2.0
        id: avd-cache
        with:
          path: |
            ~/.android/avd/*
            ~/.android/adb*
          key: avd-${{ runner.os }}-api-30

      - name: Create AVD and generate snapshot for caching
        if: steps.avd-cache.outputs.cache-hit != 'true'
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: 30
          target: google_apis
          arch: x86_64
          profile: pixel_6
          force-avd-creation: false
          emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
          disable-animations: true
          script: echo "Generated AVD snapshot for caching."

      - name: Run instrumented tests
        uses: reactivecircus/android-emulator-runner@v2
        with:
          api-level: 30
          target: google_apis
          arch: x86_64
          profile: pixel_6
          force-avd-creation: false
          emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
          disable-animations: true
          script: ./gradlew connectedDebugAndroidTest --stacktrace

      - name: Upload instrumented test results
        if: always()
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02  # v4.6.0
        with:
          name: instrumented-test-results
          path: |
            app/build/reports/androidTests/
            app/build/outputs/androidTest-results/
          retention-days: 7
```

**Features:**
- ✅ Runs on push and pull requests
- ✅ Separate jobs for unit tests, lint, and instrumented tests
- ✅ Gradle caching for faster builds
- ✅ AVD caching for faster emulator startup
- ✅ KVM acceleration for faster emulator performance
- ✅ All actions pinned to commit SHAs
- ✅ Test results uploaded as artifacts
- ✅ Instrumented tests only run if unit tests pass

## Verification

**MANDATORY:** Verify workflow is valid:

```bash
# Validate YAML syntax
yamllint .github/workflows/test.yml

# Verify workflow exists
test -f .github/workflows/test.yml && echo "✓ Test workflow created"

# Push to trigger workflow
git add .github/workflows/test.yml
git commit -m "Add CI test workflow"
git push
```

**Monitor:** Go to repository → Actions tab to see tests running

## Outputs

| Output | Location | Description |
|--------|----------|-------------|
| Test workflow | .github/workflows/test.yml | CI test automation |

## Optional Enhancements

### Add Code Coverage

If using JaCoCo, add to `app/build.gradle.kts`:

```kotlin
android {
    buildTypes {
        debug {
            enableAndroidTestCoverage = true
            enableUnitTestCoverage = true
        }
    }
}
```

### Add Test Report Comments

Add a step to comment test results on PRs:

```yaml
- name: Comment test results on PR
  if: github.event_name == 'pull_request'
  uses: EnricoMi/publish-unit-test-result-action@v2
  with:
    files: app/build/test-results/**/*.xml
```

## Troubleshooting

### "Emulator failed to start"
**Cause:** KVM not available or permissions issue
**Fix:** GitHub-hosted runners should have KVM enabled. Check runner logs.

### "Out of memory during tests"
**Cause:** Gradle daemon using too much memory
**Fix:** Add to gradle.properties: `org.gradle.jvmargs=-Xmx2048m`

### "Tests timeout"
**Cause:** Instrumented tests taking too long
**Fix:** Increase timeout or split tests across multiple jobs

## Completion Criteria

- [ ] `.github/workflows/test.yml` exists and is valid
- [ ] Workflow runs on push and pull requests
- [ ] Unit tests execute successfully
- [ ] Lint checks execute successfully
- [ ] Instrumented tests execute successfully (if configured)
- [ ] Test results uploaded as artifacts

Related Skills

android-screen-capture

16
from diegosouzapw/awesome-omni-skill

Start Android screen mirroring using scrcpy. Displays device screen in real-time on Mac with optional console logs. Use when viewing Android screen, mirroring device, or monitoring app with logs.

android-playstore-setup

16
from diegosouzapw/awesome-omni-skill

Complete Play Store setup - orchestrates scanning, privacy policy, version management, Fastlane, and workflows (Internal track only)

android-playstore-pipeline

16
from diegosouzapw/awesome-omni-skill

Complete end-to-end Android Play Store deployment pipeline setup in one command

android-fastlane-setup

16
from diegosouzapw/awesome-omni-skill

Setup Fastlane for Play Store deployment with supply and screengrab

android-espresso-dependencies

16
from diegosouzapw/awesome-omni-skill

Add Espresso and AndroidX Test dependencies to Android project

android-deploy-usb

16
from diegosouzapw/awesome-omni-skill

Build and deploy Android app to connected device via USB. Fast deployment (~2-5 seconds) using Gradle and ADB. Use when deploying, installing, or building Android apps to physical devices.

testcontainers-integration-tests

16
from diegosouzapw/awesome-omni-skill

Use when integration tests require real infrastructure (database, message queue, cache) or when mocking infrastructure is insufficient. Defines container lifecycle, test isolation, and performance optimization for Testcontainers-based testing.

blog-smoke-tests

16
from diegosouzapw/awesome-omni-skill

Run Playwright smoke tests for Denser blog application. Executes 15 tests (SMOKE-01 to SMOKE-15) against configurable environment (production, dev, or localhost) with retry support (max 3 attempts per failing test). Supports headed (visible browser) and headless modes. Collects artifacts (screenshots, trace.zip) on failures and generates HTML report. Use when testing blog functionality, verifying deployments, checking UI/API consistency, or when user requests smoke tests, playwright tests, or blog testing.

android

16
from diegosouzapw/awesome-omni-skill

Build, review, and refactor Android mobile apps (Kotlin) using modern Android patterns. Use for tasks like setting up Gradle modules, Jetpack Compose UI, navigation, ViewModel/state management, networking (Retrofit/OkHttp), persistence (Room/DataStore), DI (Hilt/Koin), testing, performance, release builds, and Play Store readiness.

android-watch-logs

16
from diegosouzapw/awesome-omni-skill

Start real-time log streaming from connected Android device using adb logcat. Shows only app's log messages. Use when monitoring app behavior, debugging, or viewing Android logs.

android-use

16
from diegosouzapw/awesome-omni-skill

Control Android devices via ADB commands - tap, swipe, type, navigate apps

android-supabase

16
from diegosouzapw/awesome-omni-skill

Supabase integration patterns for Android - authentication, database, realtime subscriptions. Use when setting up Supabase SDK, implementing OAuth, querying database, or setting up realtime.