Перейти до вмісту

Цю сторінку ще не перекладено, тому її показано англійською.

Android tests

Run Android host tests under Robolectric with elide test, and instrumented tests on a device, an emulator or a matrix with elide test --device.

Читати офлайнelide help --lang uk android-testing

На цій сторінці
Використовувати з ШІ
Відкрити в ChatGPTВідкрити в Claude
TestsLive inRun withRun on
Host testssrc/testelide testThe build machine’s JVM, under Robolectric
Instrumented testssrc/androidTestelide test --deviceA device or emulator

Host tests

Host tests are JVM tests of an Android project. Under Robolectric they read the project’s resources, assets and merged manifest, as the Android Gradle Plugin’s isIncludeAndroidResources = true makes them.

pkl
amends "elide:project.pkl"

import "elide:Android.pkl" as Android

name = "greeter"

android {
  namespace = "com.example.greeter"
  compileSdk = 36
  minSdk = 30
  resources {
    strings { ["greeting"] = "Hello from Pkl" }
  }
}

dependencies {
  android {
    androidx { ["core-ktx"] = "1.15.0" }
    robolectric = "4.16"
  }
  maven {
    testPackages {
      "junit:junit:4.13.2"
      "androidx.test:core:1.7.0"
      "androidx.test.ext:junit:1.3.0"
    }
  }
}

artifacts {
  ["app"] = new Android.AndroidApk { release = false }
}
utf-8 · pkl · Lines: 32
kotlin
// src/test/kotlin/com/example/greeter/GreetingTest.kt
package com.example.greeter

import android.content.Context
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.annotation.Config

@RunWith(AndroidJUnit4::class)
@Config(sdk = [35])
class GreetingTest {
  @Test
  fun readsTheGeneratedString() {
    val context = ApplicationProvider.getApplicationContext<Context>()
    assertEquals("Hello from Pkl", context.getString(R.string.greeting))
  }
}
utf-8 · kotlin · Lines: 20
Terminal
bash
elide test
elide test --select=class:com.example.greeter.GreetingTest
  • dependencies.android.robolectric adds Robolectric and the JUnit vintage engine that runs its JUnit 4 runners.
  • A test class names its runner: @RunWith(AndroidJUnit4::class) or @RunWith(RobolectricTestRunner::class).
  • Robolectric runs the API level the merged manifest targets unless @Config(sdk = …) says otherwise, and refuses a level it does not support; pin one it supports when compileSdk is newer.
  • The test JVM gets the --add-opens and --enable-native-access flags Robolectric needs on a current JDK, after the project’s own jvm.flags.
  • Test-only libraries contribute their manifests: add androidx.compose.ui:ui-test-manifest to testPackages to launch ComponentActivity from Compose test rules.

Host tests run against one artifact of the project, linked a second time with the test libraries: android.hostTests names it, else the first application, library or bundle the project declares.

pkl
android {
  namespace = "com.example.app"
  compileSdk = 36
  hostTests = "app-dev"
}
utf-8 · pkl · Lines: 5

Host test selection, reporters and coverage work as for any JVM test (Testing).

Instrumented tests

src/androidTest is a source set in every Android project. Its tests run on a device, never on the host: elide test does not compile them, and no artifact packages them.

text
src/main/kotlin/com/example/app/MainActivity.kt
src/androidTest/kotlin/com/example/app/MainActivityTest.kt
src/androidTest/AndroidManifest.xml        # optional
src/androidTest/res, src/androidTest/assets # optional
utf-8 · text · Lines: 4
pkl
dependencies {
  android {
    test { runner = "1.6.2"; modules { "ext-junit" }; espresso { "core" } }
  }
}
utf-8 · pkl · Lines: 5
kotlin
// src/androidTest/kotlin/com/example/app/MainActivityTest.kt
package com.example.app

import androidx.lifecycle.Lifecycle
import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class MainActivityTest {
  @Test
  fun launches() {
    ActivityScenario.launch(MainActivity::class.java).use { scenario ->
      assertEquals(Lifecycle.State.RESUMED, scenario.state)
    }
  }
}
utf-8 · kotlin · Lines: 19

androidTest sees main’s classes, its R and its dependencies, plus the instrumented-test scope: dependencies.android.test and dependencies.maven.androidTestPackages. Neither the app nor host tests see that scope.

Run them

Terminal
bash
elide test --device                                  # the attached device, else the project's emulator
elide test --device=emulator-5554                    # that device
elide test --device=small                            # a device android.devices declares
elide test --device=all                              # every declared device
elide test --device --tests=com.example.app.MainActivityTest
elide test --device --tests=com.example.app.MainActivityTest#launches

A --device value is all first, then a declared device’s name, then an attached device’s serial. --tests takes <class> or <class>#<method>, repeated or comma-separated, and needs --device; host tests are selected with --select. Paths are refused with --device.

The run:

  1. builds the app and an implicit app-androidTest APK that instruments it;
  2. uninstalls and reinstalls both, so every run starts from empty app data;
  3. runs the tests with AndroidJUnitRunner, reporting each as it finishes, with a failure’s stack trace;
  4. ends with a passed, failed and skipped count.

It fails when a test fails, when the run did not finish (the process crashed or the device went away; the running test is named), and when no test ran, including when a --tests filter matches nothing.

The test APK

Of app-androidTestIs
ClassesandroidTest’s, and the libraries of its scope that the app does not already ship
ManifestAn <instrumentation> of androidx.test.runner.AndroidJUnitRunner, merged with src/androidTest/AndroidManifest.xml
TargetThe app’s applicationId
PackageThe app’s applicationId with .test appended
SigningThe app’s own

It instruments the first APK the project declares that is neither a test APK nor minified. elide build app-androidTest builds it alone, as .dev/artifacts/app-androidTest.apk. Declaring an artifact named app-androidTest replaces it.

Declared test APKs

An APK declaring instrumentation is a test APK of its own, which android-test-<artifact> runs. A self-instrumenting APK carries the tests, the code under test and the activities they start in one package:

pkl
artifacts {
  ["app-tests"] = new Android.AndroidApk {
    applicationId = "com.example.app.test"
    release = false
    instrumentation {}
  }
}
utf-8 · pkl · Lines: 7

instrumentation.runner defaults to androidx.test.runner.AndroidJUnitRunner; instrumentation.targetPackage names another installed app to instrument. A target package the build did not install has its data cleared before the run.

Test devices

android.devices names virtual devices to run instrumented tests on, as Gradle’s managed devices do:

pkl
android {
  namespace = "com.example.app"
  compileSdk = 36
  devices {
    ["pixel"] {}
    ["small"] { deviceProfile = "small_phone"; api = 34 }
  }
}
utf-8 · pkl · Lines: 8
Terminal
bash
elide test --device=pixel
elide test --device=all
elide build android-test-app-on-all --no-window --install-sdk   # headless CI, images installed

A device takes the fields android.device does (Run and debug); its AVD defaults to <project>-<device>. A run creates the AVD if it is missing, boots it or adopts it if it is already running, and stops it afterwards if it booted it, so a matrix does not outlive the build. Names are letters, digits, _ and -, starting with a letter; all is reserved.

In CI

yaml
- uses: elide-dev/setup-elide@v4.2.0
- run: elide install --accept-android-licenses
- run: elide test
- run: elide build android-test-app-on-all --no-window --install-sdk
utf-8 · yaml · Lines: 4

Instrumented tests on Linux runners need KVM (Headless hosts, CI and WSL). android/test and android/test/host in elide mcp run the same targets for an agent and return every test’s outcome (Editors and agents).

Чи була ця сторінка корисною?