diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 8729445ce..710747f24 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -74,3 +74,22 @@ steps: tar -xzf dist.tar.gz make test-ios-e2e plugins: *plugins + + - label: ':android: Test Android E2E' + depends_on: build-react + command: | + buildkite-agent artifact download dist.tar.gz . + tar -xzf dist.tar.gz + echo "--- :robot_face: Starting Android emulator" + start-android-emulator \ + --system-image "system-images;android-34;google_apis;arm64-v8a" \ + --device "pixel_5" + echo "--- :android: Running Android instrumented tests" + make test-android-e2e + agents: + queue: mac-metal + plugins: *plugins + artifact_paths: + - 'android/app/build/reports/androidTests/connected/**/*' + - 'android/app/build/outputs/androidTest-results/connected/**/*' + - 'android/app/build/outputs/connected_android_test_additional_output/**/*' diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index bc18059cf..4cb01731a 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -51,6 +51,28 @@ android { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + // Buildkite Test Engine: upload per-test results when a token is present in the env. + // Absent locally → no listener is registered and the collector is fully inert. + // Build metadata env vars are forwarded so uploaded results link back to the CI job: + // https://github.com/buildkite/test-collector-android/blob/main/CI_CONFIGURATION.md#buildkite + System.getenv("BUILDKITE_ANALYTICS_TOKEN_ANDROID_E2E")?.takeIf { it.isNotBlank() }?.let { token -> + testInstrumentationRunnerArguments["listener"] = + "com.buildkite.test.collector.android.InstrumentedTestCollector" + testInstrumentationRunnerArguments["BUILDKITE_ANALYTICS_TOKEN"] = token + + listOf( + "BUILDKITE_BUILD_ID", + "BUILDKITE_BUILD_URL", + "BUILDKITE_BRANCH", + "BUILDKITE_COMMIT", + "BUILDKITE_BUILD_NUMBER", + "BUILDKITE_JOB_ID", + "BUILDKITE_MESSAGE", + ).forEach { key -> + System.getenv(key)?.let { value -> testInstrumentationRunnerArguments[key] = value } + } + } + buildConfigField("String", "WP_ENV_SITE_URL", "\"${wpEnvCredentials["siteUrl"] ?: ""}\"") buildConfigField("String", "WP_ENV_SITE_API_ROOT", "\"${wpEnvCredentials["siteApiRoot"] ?: ""}\"") buildConfigField("String", "WP_ENV_AUTH_HEADER", "\"${wpEnvCredentials["authHeader"] ?: ""}\"") @@ -102,4 +124,9 @@ dependencies { testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(libs.androidx.espresso.web) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.compose.ui.test.junit4) + androidTestImplementation(libs.buildkite.test.collector.instrumented) + debugImplementation(libs.androidx.compose.ui.test.manifest) } diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index ed8aedc4f..27536b9a6 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -6,6 +6,7 @@ coreKtx = "1.13.1" junit = "4.13.2" junitVersion = "1.2.1" espressoCore = "3.6.1" +espressoWeb = "3.6.1" appcompat = "1.7.0" material = "1.12.0" activity = "1.9.0" @@ -22,12 +23,14 @@ activityCompose = "1.9.3" jsoup = "1.18.1" okhttp = "4.12.0" detekt = "1.23.8" +buildkite-test-collector = "0.4.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } +androidx-espresso-web = { group = "androidx.test.espresso", name = "espresso-web", version.ref = "espressoWeb" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } material = { group = "com.google.android.material", name = "material", version.ref = "material" } androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" } @@ -47,10 +50,13 @@ androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" } androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } androidx-compose-material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended" } androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } +androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } +androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } jsoup = { group = "org.jsoup", name = "jsoup", version.ref = "jsoup" } okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" } okhttp-mockwebserver = { group = "com.squareup.okhttp3", name = "mockwebserver", version.ref = "okhttp" } +buildkite-test-collector-instrumented = { group = "com.buildkite.test-collector-android", name = "instrumented-test-collector", version.ref = "buildkite-test-collector" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }