This is a demonstration of how to setup CI for Android projects. In this repository, we have a simple counter application built with Jetpack Compose. We aim to automate the build & instrumented testing on every push/merge to main branch.
This is how the app looks like:
Screenshot of the app |
In this project, we have unit tests CounterStateTest
for testing the CounterState
class, the stateholder of the application with increment()
and decrement()
mutating methods. Also we have instrumented tests CounterAppTest
to validate the application UI will interact properly with CounterState
state class.
Unit test execution in Android Studio |
Instrumented test execution in Android Studio |
Gradle makes us easier to quickly spin up emulated devices with the required specifications. In the app/build.gradle.kts
, we provide the specification of a medium sized phone and tablet. Also we create a device group with both devices included:
testOptions {
managedDevices {
localDevices {
create("mediumPhoneApi34AospAtd") {
device = "Medium Phone"
apiLevel = 34
systemImageSource = "aosp-atd"
}
create("mediumTabletApi34AospAtd") {
device = "Medium Tablet"
apiLevel = 34
systemImageSource = "aosp-atd"
}
}
groups {
create("mediumPhoneAndTabletApi34AospAtd") {
targetDevices.add(devices["mediumPhoneApi34AospAtd"])
targetDevices.add(devices["mediumTabletApi34AospAtd"])
}
}
}
}
This gives us a Gradle task :app:mediumPhoneAndTabletApi34AospAtdGroupDebugAndroidTest
which builds the project, spins up the emulator instances with aosp-atd
image (a light-weight image specifically for instrumentation testing) for both medium sized phone and tablet, executes the test cases and generate reports.
For automating build generation and test execution, we use a pre-built Android SDK toolchain container image anandbose16/android-sdk (GitHub) to minimise the setup time and simplifying the configuration. The container image meets the requirements for basic Android development environment such as Android SDK toolchain, Gradle, OpenJDK, emulator and basic command-line utilities for post tasks.
The ideal workflow:
- Use the container image
anandbose16/android-sdk:34
- Checkout code
- Generate build with
:app:assembleDebug
task - Execute lint with
:app:lintDebug
task - Execute unit tests with
:app:testDebugUnitTest
task - Execute instrumented tests with
:app:mediumPhoneAndTabletApi34AospAtdGroupDebugAndroidTest
task - Upload the APK file and the test reports to artifacts storage.
Note: The implementation of the workflow is different on each platform, and platform implied limitations will apply.
Platform | Repo | Configuration | Supports Build | Supports Lint | Supports Unit Tests | Support Instrumented Tests |
---|---|---|---|---|---|---|
GitHub | Repo | .github/workflows/main.yml | ✅ | ✅ | ✅ | ✅ |
GitLab | Repo | .gitlab-ci.yml | ✅ | ✅ | ✅ | ⛔[1] |
BitBucket | Repo | bitbucket-pipelines.yml | ✅ | ✅ | ✅ | ⛔[2] |
Azure DevOps | Repo | azure-pipelines.yml | ✅ | ✅ | ✅ | ⛔[3] |
[1][2] Running emulators in GitLab and BitBucket pipelines are not supported due to lack of KVM hypervisor.
[3] Running emulators in Azure is not supported due to lack of KVM hypervisor support. However, Azure provides a task AppCenterTest@1 requires paid subscription in VS AppCenter.