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).