Essaim
On real phones

Your Android tests on a swarm of real phones

You push your APKs, Essaim splits the suite across several real devices and aggregates the JUnit results. Each device returns its verdict, its logs and its screenshots: the shard that fails is identified, not guessed.

No credit card to start. Secure payment through Stripe when you change plan.

Your suite 42 tests 3 shards Redmi Note 13 shard 1 · 14 tests SM-X110 · tablet shard 2 · 14 tests next device shard 3 · 14 tests Aggregated JUnit 42 tests 0 failed · 0 duplicate exit 0

Three shards in parallel, one single JUnit result.

What it does

Concretely

Deterministic sharding

An instrumentation run is split by class (`extra.class`), not blindly: every shard knows exactly which classes it runs. Aggregation spots tests executed twice and tests that never ran.

JUnit aggregation

Essaim reads back the JUnit XML of every device, computes the totals and details the failures. The exit code is 0 when everything is green, 1 otherwise — in your CI, it blocks the merge.

Minutes, not opaque credits

The unit of account is the device minute. The cost of a run is computed before it starts, a minimum is reserved at creation time, and the real usage is settled at the end.

API, CLI and webhook

`POST /api/v1/runs`, the CLI `essaim run --app app.apk --test app-test.apk --devices pixel,samsung-a`, and a `run.completed` webhook signed with HMAC (X-Hangar-Signature).

Uploads stay with the platform

Essaim stores no bytes: the upload is relayed to Hangar, and the customer only talks to Essaim through a signed URL of its own. Artifacts are served the same way.

Aggregation

One table at the end

Every device returns its JUnit XML. Essaim reads them back, adds them up, and spots what a naive sum lets through: a test run twice, a test that never ran.

essaim run --app app.apk --test app-test.apk --devices pixel,samsung-a
ShardDeviceClassesTestsFailuresTime
1Redmi Note 13LoginTest, CartTest1401 min 12
2SM-X110 (tablet)SearchTest, ProfileTest14058 s
3next deviceCheckoutTest, SettingsTest1401 min 03
Aggregated6 classes4202 min 04

run twice: 0 · never run: 0 · exit 0

The exit code is 0 when everything is green, 1 otherwise: in your CI, that is what blocks the merge.

In all honesty

What we do not do

A product that hides its limits wastes everybody's time. Here are ours, today.

  • An instrumentation run requires `test_package`: Essaim does not read APKs and the platform needs it. Without it, 400.
  • No video per device: neither instrumentation nor flows produce one today (only a `capture` job records the screen on the platform side).
  • The multi-model matrix and the robot explorer (`monkey`) are not built.
  • The GitHub Action, the GitHub App (build by Essaim) and building in our infrastructure are phase 2.
  • An upload is buffered in memory (256 MiB by default) before being relayed to Hangar: no streaming.
  • A flow run costs two jobs (`install` then `flow`): the platform has no job combining both. And Maestro does not install on MIUI until "Install via USB" is enabled.
Questions

Frequently asked questions

Can I run an instrumentation run without `test_package`?

No: the platform runs `am instrument <package>/<runner>` and Essaim does not read APKs. Without `test_package` the request is rejected with a 400.

Is there a video per device?

Not today. On the platform side only a `capture` job records the screen: the `record_video` parameter of a `flow` job is accepted but ignored. The evidence delivered is `junit.xml`, `tests.json`, `instrument.log` and `logcat.txt` for instrumentation; `report.xml`, `steps.json`, `maestro.log` and the screenshots for flows.

Does synchronous mode wait for the run to finish?

At most 120 seconds. Beyond that the answer is a 202 and you have to poll the run — or listen to the `run.completed` webhook.

Can I run a matrix of several models?

Not in phase 1. The selector targets a model or an Android version, but the multi-model matrix and the robot explorer (`monkey` without a package name) are not built: the platform requires the package, which Essaim cannot read from an APK.

Try it on a real phone

Create an account, take a key, run your first test. It is free to start.