# Share an Android Test Report — Espresso Results at a URL

Canonical: https://commareports.com/share-android-test-report
Published: 2026-08-31

> connectedAndroidTest writes an HTML report into app/build/reports that dies with the CI runner. Publish it: one link per run, failure screenshots attached, threads on the flaky test.

# Share an Android test report

`./gradlew connectedAndroidTest` produces a real HTML report with the
failing class, the assertion, the timing and the device it ran on. It
lands in `app/build/reports/androidTests/connected/` on whichever machine
had the emulator attached.

In CI that becomes an artifact zip, and the actual failure reaches the
team as a screenshot of the Android Studio run pane.

## Two reports, two locations

Worth being precise, because people routinely publish the wrong one:

```bash
# instrumentation / Espresso tests — needs a device or emulator
./gradlew connectedAndroidTest || true
# → app/build/reports/androidTests/connected/index.html

# local unit tests — no device
./gradlew testDebugUnitTest || true
# → app/build/reports/tests/testDebugUnitTest/index.html
```

Both are **directories** — `index.html` plus per-class pages, `css/` and
`js/`. Publish `index.html` alone and you get an unstyled index whose
drill-down links are all dead.

## Drop the folder in

Drag `app/build/reports/androidTests/connected/` (or a zip) into
[Comma](https://commareports.com/):

- `index.html` becomes the **report body** — the page carrying the comment
  layer.
- Per-class pages, CSS and JS upload alongside it, with relative
  references rewritten, so the drill-down from summary to failing class to
  stack trace resolves.
- Scripts run inside a sandboxed iframe (`allow-scripts`, no
  `allow-same-origin`), so the report's tabs and sorting keep working.

## From CI

```bash
./gradlew connectedAndroidTest || true

curl -fsS -X PATCH "https://commareports.com/api/v1/reports/$REPORT_ID" \
  -H "Authorization: Bearer $COMMA_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --rawfile html app/build/reports/androidTests/connected/index.html \
        --arg title "Espresso — $(git rev-parse --short HEAD)" \
        '{title: $title, html: $html}')"
```

The API is JSON-only, so the per-class pages go up through
`POST /api/v1/reports/$REPORT_ID/assets` as base64 — one call per file,
worth scripting once. See the [API reference](/docs/api).

Use a [scoped token](/docs/api-tokens) (`reports:write`) from CI secrets
and `PATCH` a saved report id, so one URL accumulates a revision per run
instead of a new orphan link every build. Mark the step `if: always()`.
See [publishing from CI](/ci).

## Attach the screenshots

An Espresso failure — "NoMatchingViewException: could not find view with
id …" — is nearly meaningless as text. The screenshot is the evidence, and
it normally expires with the artifact retention window.

Upload failure screenshots as report assets and they live next to the
report and the discussion permanently. If you use a screenshot rule or a
library like Spoon or Shot, point it at a directory and upload that
directory with the report.

## One report id per device configuration

Instrumentation results are only meaningful alongside the device they came
from. A test that fails on API 29 and passes on API 34 is a different
conversation from one that fails everywhere.

Keep a report id per matrix leg — phone, tablet, minSdk — and `PATCH` each
on every run. Each URL then accumulates a device-specific history, and
diffing two revisions of the same leg shows what actually changed rather
than what the matrix happened to schedule.

## Flakiness gets a memory

The reason to publish rather than screenshot is that Android UI tests are
flaky in patterns, and the patterns are what get lost.

Select the test, leave a thread — "flakes on the emulator when the
animation scale isn't zero" — and it stays anchored to that test across
runs. The next person to see it red finds the note instead of spending an
afternoon rediscovering it. See [commenting on HTML](/comment-on-html).

## Who can see it

Per report: private, your team, any signed-in user with the link, or
public. Test reports name internal screens and API paths, so team is the
usual default. Domain-gating, password gates and expiring links are
Enterprise. See [sharing & access control](/docs/sharing).

## Limits

- **Entry HTML: 5 MB.** Assets: 25 MB per file, 250 MB and 500 files
  total — screen recordings can hit the per-file limit, so prefer
  screenshots or trim them.
- **Scripts run, sandboxed** — no same-origin access.
- **60 requests/minute per token.**

## Try it

Comma is free — unlimited reports, unlimited commenters, unlimited
revision history.

**[Publish a test report →](https://commareports.com/)**

### Related

- [Share an Xcode test report](/share-xcode-test-report) — the iOS side
- [Share a Gradle test report](/share-gradle-test-report) · [Share a JUnit report](/share-junit-report)
- [Share a JaCoCo coverage report](/share-jacoco-report) · [Share an Allure report](/share-allure-report)
- [Publish from CI](/ci)
