Hi everyone,
In November 2022, the Gradle-managed devices were introduced for Android. It hopefully would make running tests more reliable by adding consistency between local and CI environments.
The Gradle task will simply take over anything related to creating the emulator, running the instrumented tests, and providing the test results in the build folder. The task will even automatically detect the CPU type of the environment and set up the device accordingly, which means the same config can run on a local ARM environment and on an x86 CI environment without changes. This is all simpler, requires less configuration, and Gradle tasks are more familiar to Android developers. Also, it is supported by the Android team at Google.
All one has to do, is to add the device in their module’s build.gradle
file:
android {
testOptions {
managedDevices {
devices {
maybeCreate<com.android.build.api.dsl.ManagedVirtualDevice>("pixel2api31").apply {
device = "Pixel 2"
apiLevel = 31
systemImageSource = "google"
}
}
}
}
}
Now, the instrumented tests for the debug
build variant can be run using ./gradlew pixel2api31DebugAndroidTest
More info about Gradle Managed devices in Android official docs.
The Challenge is to run on CircleCI: using it requires vt-x/haxm support.
The MacOS executors seem to provide vt-x, and I also used them before CircleCI provides the android machine images to manually set up the Android environment. Now I am back to the MacOS to use the gradle-managed devices.
The following script installs the android command line tools, accepts the licenses, and eventually runs the instrumented tests:
# install android commandline tools and required packages
brew install --cask android-commandlinetools
yes | sdkmanager "tools" "platform-tools" "build-tools;33.0.1" "platforms;android-33" "system-images;android-31;google_apis;x86_64" "extras;intel;Hardware_Accelerated_Execution_Manager"
# accept licenses
yes | sdkmanager --licenses
export ANDROID_HOME=/usr/local/share/android-commandlinetools
export PATH=$PATH:$ANDROID_HOME/tools:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools
# install intel haxm
cd $ANDROID_HOME/extras/intel/Hardware_Accelerated_Execution_Manager/
chmod +x silent_install.sh
sudo ./silent_install.sh
/usr/local/share/android-commandlinetools/tools/emulator -accel-check
cd ~/project/
# run the instrumented tests using gradle managed devices
./gradlew pixel2api31DebugAndroidTest
Using this script in a step will endup with the following error:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:pixel2api31Setup'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.ManagedDeviceSetupTask$ManagedDeviceSetupRunnable
> java.lang.IllegalStateException: Gradle was not able to complete device setup for: dev31_google_apis_x86_64_Pixel_2
This could be due to having insufficient resources to provision the number of
devices requested. Try running the test again and request fewer devices or
fewer shards.
The full CircleCI step (having the script mentioned above under /scripts/install-android-tools-and-run-tests.sh
):
run_instrumented_tests:
macos:
xcode: 11.7.0
resource_class: large
steps:
- checkout
- run:
name: Run instrumented tests
command: |
./scripts/install-android-tools-and-run-tests.sh
- store_test_results:
path: app/build/outputs/androidTest-results
- store_artifacts:
path: app/build/outputs/managed_device_android_test_additional_output/pixel2api31/screc
Even though the macOS machines on CircleCI seem to support nested virtualization, this is failing.
Any help to fix this is appreciated!