Skip to content

ci(android): run Gutenberg-module instrumented tests#472

Open
jkmassel wants to merge 1 commit intotrunkfrom
jkmassel/wire-gutenberg-instrumentation
Open

ci(android): run Gutenberg-module instrumented tests#472
jkmassel wants to merge 1 commit intotrunkfrom
jkmassel/wire-gutenberg-instrumentation

Conversation

@jkmassel
Copy link
Copy Markdown
Contributor

@jkmassel jkmassel commented Apr 24, 2026

Summary

  • Adds a test-android-library-e2e make target that runs :Gutenberg:connectedDebugAndroidTest, and wires it into Buildkite as a new :android: Test Android Library Instrumented step on the mac-metal queue — parallel to the existing :app E2E step.
  • Hooks the step into Buildkite Test Engine via the instrumented-test-collector, gated on the new BUILDKITE_ANALYTICS_TOKEN_ANDROID_LIBRARY_E2E secret so timings and flakes show up in the dashboard alongside the existing E2E suite.
  • Extracts the collector-config block that was duplicated between :app and :Gutenberg into a buildSrc helper, and adopts it in both modules.
  • Migrates the :Gutenberg module's androidTest assertions from org.junit.Assert.* to kotlin.test.*, and adds androidTestImplementation(kotlin("test")). This resolves the pre-existing failures that lighting up the CI job exposed.

Context

The :Gutenberg module has carried instrumented test sources under androidTest/ since #367, but no CI job has ever executed them — make test-android-e2e only covers :app:connectedDebugAndroidTest. Turning them on here surfaced failures in org.wordpress.gutenberg.http.InstrumentedFixtureTests (multipartParsingErrorCases, requestParsingErrorCases) that this PR is the right place to fix.

New renderer instrumented tests from #470 will also get coverage once both PRs land.

Root Cause

The failures produced comparisons that looked wrong but weren't:

expected:<[]invalidEncoding> but was:<[Rejects non-UTF-8 header bytes (0xFF 0xFE BOM-like): expected invalidEncoding but got ]invalidEncoding>

InstrumentedFixtureTests imported JUnit 4's org.junit.Assert.assertEquals, whose signature is (message, expected, actual) — message first. Two catch blocks called it in Jupiter/kotlin.test order (expected, actual, message), so the description string landed in the actual slot and got compared against an errorId. The parser behavior is fine.

Fix

Rather than just reordering the two bad call sites, migrate the androidTest sources to kotlin.test.*. That matches what a Kotlin author naturally writes ((expected, actual, message) / (actual, message)), so the bug can't re-occur the same way.

  • android/buildSrc/src/main/kotlin/BuildkiteTestCollector.kt: New top-level configureBuildkiteTestCollector(args: MutableMap<String, String>, tokenEnvName: String). Registers the listener, forwards Buildkite metadata env vars, and is inert when the token isn't set. Takes the testInstrumentationRunnerArguments map as a parameter rather than extending an AGP type — this keeps buildSrc AGP-free and avoids a plugin-classpath conflict with each module's alias(libs.plugins.android.*) application.
  • android/Gutenberg/build.gradle.kts / android/app/build.gradle.kts: Call the helper from defaultConfig {} with testInstrumentationRunnerArguments and their respective token env vars (_ANDROID_LIBRARY_E2E and _ANDROID_E2E). Replaces ~23 lines of duplicated config in each.
  • android/Gutenberg/build.gradle.kts: Adds androidTestImplementation(kotlin("test")). kotlin.test is already on the JVM testImplementation classpath; this just adds it for androidTest.
  • InstrumentedFixtureTests.kt / ExampleInstrumentedTest.kt: Swap org.junit.Assert.*kotlin.test.* and reorder all call sites. Also collapses a few assertNotNull(...); x!! pairs into val x = assertNotNull(...) since kotlin.test's assertNotNull returns the non-null value.

AndroidX's JUnit 4 test runner is unchanged — that's what AndroidJUnitRunner drives; only the assertion style changes. JVM unit tests under src/test/ already use kotlin.test and are untouched.

Commits

  1. ci(android): run Gutenberg-module instrumented tests — new Buildkite step, Test Engine collector wiring, and buildSrc helper adopted by both Android modules.
  2. refactor(android): migrate androidTest assertions to kotlin.test — the assertion migration that fixes the failures.

Test plan

  • CI's new :android: Test Android Library Instrumented step runs on this PR and passes.
  • The existing :app E2E step still passes in parallel — Test Engine results should still show up for it under its existing suite, since the helper is functionally equivalent to the inline block it replaced.
  • Results appear in Buildkite Test Engine under the new Android Library E2E suite.

@github-actions github-actions Bot added the [Type] Build Tooling Issues or PRs related to build tooling label Apr 24, 2026
@jkmassel jkmassel force-pushed the jkmassel/wire-gutenberg-instrumentation branch 5 times, most recently from 908aa16 to a8eb19b Compare April 24, 2026 19:23
Runs `:Gutenberg:connectedDebugAndroidTest` on the `mac-metal` queue
and uploads results to Buildkite Test Engine (suite:
`gutenbergkit-android-library-e2e`).

## Wiring

- `buildSrc` helper `configureBuildkiteTestCollector` registers the
  Buildkite JUnit listener when
  `BUILDKITE_ANALYTICS_TOKEN_ANDROID_LIBRARY_E2E` is present. Taking
  `testInstrumentationRunnerArguments` as a plain
  `MutableMap<String, String>` keeps `buildSrc` free of an AGP
  dependency — avoids a plugin-classpath conflict with each module's
  `alias(libs.plugins.android.*)`.
- `:app` module migrated to the same helper with its existing
  `BUILDKITE_ANALYTICS_TOKEN_ANDROID_E2E` token.
- `:Gutenberg:androidTest` uses `kotlin.test.*` — consistent with
  `src/test/`. JUnit 4's `assertEquals(message, expected, actual)` is
  a footgun versus `kotlin.test.assertEquals(expected, actual, message)`.
- Deletes the `ExampleInstrumentedTest` placeholder.

## Fail-loud instead of silent green

The collector library silently swallows config and upload errors — a
missing token makes the listener inert; HTTP errors only log. Without
extra wiring the suite goes green while Test Engine receives nothing.

- `configureBuildkiteTestCollector` fails configuration on Buildkite
  (detected via `BUILDKITE_BUILD_ID`) if the token is missing or blank.
- `BUILDKITE_ANALYTICS_DEBUG_ENABLED=true` so the happy path also
  emits traces, not just errors.
- `test-android-library-e2e` clears logcat, runs the gradle task,
  dumps device logcat to `build/outputs/buildkite-logs/device-logcat.txt`
  (uploaded as an artifact), and greps for the library's `*-ERROR`
  log prefixes. Any on-device upload error fails the step.
- Test APK manifest declares `android.permission.INTERNET`, scoped to
  `androidTest/` so published-library consumers don't inherit it.
  Without it the library logs
  `Error uploading test analytics data: Permission denied (missing INTERNET permission?).`

Verified end-to-end: Test Engine run
`f3f3afb4-efa4-876c-ba05-4a4c9621d64a` received on build 2042.
@jkmassel jkmassel force-pushed the jkmassel/wire-gutenberg-instrumentation branch from a8eb19b to ba4d724 Compare April 24, 2026 21:40
@jkmassel jkmassel requested review from oguzkocer April 24, 2026 22:02
@jkmassel
Copy link
Copy Markdown
Contributor Author

e2e test failures will be resolved by #473

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Build Tooling Issues or PRs related to build tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant