android-ci-tests

Setup GitHub Actions workflow for running Android tests in CI

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "android-ci-tests" with this command: npx skills add hitoshura25/claude-devtools/hitoshura25-claude-devtools-android-ci-tests

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

InputRequiredDefaultDescription
project_pathYes.Android project root

Process

Step 1: Create CI Test Workflow

Create .github/workflows/test.yml:

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:

# 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

OutputLocationDescription
Test workflow.github/workflows/test.ymlCI test automation

Optional Enhancements

Add Code Coverage

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

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

Add Test Report Comments

Add a step to comment test results on PRs:

- 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

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

android-playstore-setup

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

android-playstore-scan

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

android-proguard-setup

No summary provided by upstream source.

Repository SourceNeeds Review