AOSP Expert & Production Engineering
2 min read

JUnit for AOSP

JUnit 4 in AOSP

In the Android Open Source Project (AOSP), JUnit 4 is the standard framework for writing Java and Kotlin unit tests. While modern application development heavily relies on Gradle, AOSP utilizes the Soong build system (Android.bp).

To define a JUnit test suite in AOSP, you use the android_test module type. This module packages your test classes and their dependencies into an APK, allowing them to be executed on a target device or emulator.

Test Runner Setup

An android_test module requires an AndroidManifest.xml that declares the test runner. The AndroidJUnitRunner is the standard instrumentation runner that bridges JUnit and the Android runtime.

Here is a typical Android.bp configuration for a unit test:

android_test {
    name: "MyFrameworkTests",
    srcs: ["src/**/*.java"],
    static_libs: [
        "androidx.test.runner",
        "androidx.test.ext.junit",
        "mockito-target-extended-minus-junit4",
    ],
    test_suites: ["device-tests"],
}

The corresponding AndroidManifest.xml must declare the instrumentation:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.myframework.tests">

    <instrumentation
        android:name="androidx.test.runner.AndroidJUnitRunner"
        android:targetPackage="com.android.myframework"
        android:label="Tests for MyFramework" />
</manifest>

Running Tests with atest

atest is a powerful command-line tool in AOSP designed to simplify test execution. It automatically finds the test module, builds the necessary dependencies, pushes the APK to the device, and runs the tests.

# Source the build environment
source build/envsetup.sh
lunch aosp_husky-trunk_staging-userdebug

# Run the entire test module
atest MyFrameworkTests

# Run a specific test class
atest MyFrameworkTests:com.android.myframework.MyServiceTest

# Run a single test method
atest MyFrameworkTests:com.android.myframework.MyServiceTest#testStartup

atest seamlessly integrates with TradeFed under the hood, parsing the output and presenting it in a readable format.

Test Result Interpretation

When atest finishes, it provides a summary of passed, failed, and ignored tests. If a test fails, investigating the root cause requires diving into the logs.

atest outputs a path to a detailed TradeFed log directory. You can inspect the host_log.txt for build and deployment issues, and logcat for runtime exceptions during the test execution.

# Example logcat command to filter for test failures
adb logcat -d | grep -iE "TestRunner|Exception|FATAL"

In AOSP development, flaky tests (tests that pass and fail intermittently) are highly problematic. When encountering a failure, it is crucial to determine if the failure is deterministic (a real bug) or environmentally dependent (e.g., relying on timing or network state).