A mobile agent can follow the same actions on two Android devices and still face different tasks. One account may have access to a work order while another does not. The work order may already contain an attachment. A runtime permission may have been granted in an earlier run, or the app may open on a different screen. If these starting conditions are not deliberate, a changed result may come from the fixture rather than the agent.

A test fixture is the prepared context in which a task runs: the identity and access scope, the relevant backend data, the permission state, and the app’s entry state. It makes the intended starting conditions concrete and checkable. It is related to device state, but it is not the same thing as resetting a device. Clearing app storage, for example, does not necessarily restore a server-side record, recreate an account role, or establish the permission state required by a test.

Consider a field-service agent asked to attach a photo to an existing maintenance work order. A useful test needs more than an installed app and a reachable phone. The account must be able to open the intended work order; the work order should be open and have no existing attachment; the app should be at the expected entry point; and the relevant access state should match the behavior being evaluated. If the flow uses an in-app camera feature that requests runtime permission, define that permission state; if it uses Android's system photo picker, define and verify the picker path instead of assuming a broad storage permission is required. Only then can the run distinguish an agent error from an inaccessible record or an unexpected starting state.

Define the fixture from the question

Start by asking what the run is meant to establish. If the question is whether an agent can attach a photo after being asked to do so, define the smallest set of conditions that could change that outcome:

  • Identity and access: a test user in the intended tenant, with the role needed to view and update the work order.
  • Backend data: a known work-order identifier, an open status, and no pre-existing attachment.
  • Access condition: the access path required by the app, such as a known camera-permission state for an in-app capture flow that requests it, or an expected system photo-picker path with test media available. Set grant/denial deliberately when permission handling is the test subject.
  • App context: the build under test, the intended signed-in account, and the work-order detail screen as the starting point.

The test case then checks whether the expected attachment appears on the work order. That outcome is not an initial fixture condition.

This is not a universal fixture schema. It is a compact way to name the conditions that matter to this particular claim. Do not fix unrelated attributes just because they are available. Conversely, do not leave a condition implicit when changing it could alter the run.

For an in-app camera flow that requests camera permission, a fixture record might look like this:

fixture_id: work-order-photo-v1
identity:
  tenant: agent-test
  role: field-technician
data:
  work_order: WO-TEST-042
  status: open
  attachments: []
app:
  build: <build-under-test>
  start_screen: work_order_detail
access_condition:
  # This example uses an in-app camera flow that requests CAMERA.
  in_app_camera_permission: granted
verify_before_run:
  - account can access the work order
  - work order is open and has no attachments
  - camera permission is granted for the tested app
  - expected app build and entry screen are present

For a system photo-picker flow, the access condition would describe the picker path and the pre-run check would confirm that the intended test media is available for selection. The values above are illustrative. This is a human-readable fixture description, not an ARMARRAY API format or a platform-specific command. A real workflow can represent the same information in a test framework, setup script, database seed, or run manifest.

Prepare identity and data as a controlled pair

Accounts and records should be prepared together because access is part of the test context. A seeded work order is not a valid starting point if the chosen identity cannot see it; an account with the right role is not enough if the target record is missing or already changed.

Use dedicated test identities and non-production data. Where runs can overlap, avoid having several workers mutate the same account and record. Give each attempt an isolated data namespace or serialize access to a shared fixture. Otherwise, one run may add the attachment that a second run expected not to exist. The second result then reflects a fixture race, not a difference in agent behavior.

Make setup repeatable. A preparation step should either create the intended starting state or verify that it already exists exactly as required. If a previous run left the record in a changed state, the setup should reseed it or reject it; it should not silently continue. Record the fixture version and the identifiers of the resources used by the attempt so that the result can be interpreted later.

Managed test environments may offer their own ways to supply test credentials. For example, Firebase Test Lab's Robo test supports test-account sign-in and cautions against using credentials associated with real users. That is one product-specific setup option, not a universal fixture model; the underlying requirement remains to use an identity and data scope designed for testing.

Reusing a fixture can be efficient when it is immutable or reliably restored. Reuse becomes risky when the tested action changes shared server data, account settings, or permissions. The relevant question is not whether a fixture is old, but whether its required properties have been checked for this run.

Treat permissions as part of the starting context

Android runtime permissions are not a decorative setting. The app may need to request a permission at runtime, and the user’s choice and prior interaction history can affect what the app sees. Android’s runtime-permission guidance calls for checking permission status and handling grant or denial rather than assuming that a prompt will appear in a particular way.

Decide whether permission state is a controlled baseline or the subject of the test. For an in-app capture flow that requests camera permission, prepare and verify the intended state before the agent starts. For a system photo-picker flow, verify that the intended media is available, then record what the agent actually selects. For a permission-handling run, define the intended denied or not-yet-granted state and observe the actual prompt and outcome. Android notes that some photo use cases can be fulfilled without declaring a permission, so do not infer a permission requirement from the task label alone. Do not let a previous attempt's choice determine the next attempt accidentally.

The exact setup method depends on the test environment and Android version. The important fixture property is the observed state presented to the app, not merely that a setup command was issued. When permission behavior itself is under test, keep that variable explicit and do not compare it with a run that started from a different permission state as if only the agent changed.

Verify the fixture before starting the agent

Setup succeeding is not proof that the intended context exists. Before dispatch, read back the declared preconditions from the systems that govern the run: check account access and record state through the relevant service, inspect the permission or test-media condition, and confirm the app build and entry screen. Record what passed and failed for this attempt rather than relying only on the setup step's response.

This creates a useful boundary between fixture failure and agent failure. If the record is absent before execution, the run cannot fairly test whether the agent updates it. Mark the attempt as invalid or setup-failed according to the evaluation design, repair the fixture, and run again. Do not score it as an agent failure. If the preconditions pass and the agent then fails to attach the photo, that is evidence about the tested behavior.

A concise pre-run gate could be:

  1. Resolve the fixture version and the resources allocated to this attempt.
  2. Independently observe each declared precondition through the app or underlying service.
  3. Record the verification result and its time, linked to the attempt.
  4. Start the agent only when the required checks pass.

The checks should be proportional to the claim. A simple screen-navigation task may not need a backend record assertion. A task whose outcome changes remote data should verify that data before and after the run.

A mobile-agent test fixture is prepared from identity, data, access, and app entry conditions; the starting preconditions are verified before a real Android run produces evidence, followed by cleanup or reseeding for the next attempt.

Capture the result before cleanup

After the attempt, capture what actually happened: relevant screen or state snapshots, actions and resulting observations, the work order's final attachment state, and any error or recovery event. Preserve event times where they are needed to interpret the sequence. If the UI shows an attachment queued but the backend has not confirmed it, preserve that distinction. A visible intermediate state and a persisted result are not interchangeable evidence.

Only after recording the outcome should the workflow clean up or reseed mutable resources. Teardown may remove an uploaded test attachment, restore the record, revoke a temporary permission, or retire the identity. The cleanup policy depends on the test and the system being exercised. In some runs, retaining the changed record is necessary for investigation; in others, it would contaminate later attempts.

A device reset can restore local device or app state; fixture cleanup also covers identities and data in the systems the task uses. Because a fixture includes app and permission conditions, reset may be one part of restoring it. Reset alone does not prove that the full fixture is ready, and cleanup does not replace pre-run verification. This extends the broader discussion of device state management with a concrete account-and-data lifecycle.

Make the starting conditions part of the run record

A result is easier to compare when its fixture is identifiable. Keep a compact run record that links the evidence artifacts to the task and attempt, fixture version, identity or safe identity reference, seeded data identifiers, access condition, app build and entry point, pre-run verification result, and cleanup outcome. The record identifies the evidence and its starting context; it need not duplicate the screenshots or action trace. Do not store secrets in the run record; use references to a controlled credential store where needed.

This also connects to the test-case definition. A case states the goal, preconditions, completion rule, and required evidence; the fixture is the operational preparation that makes those preconditions true for a particular attempt. The two should agree, but they serve different purposes. The test-case method is described in From a User Goal to a Testable Mobile AI Case.

Real Android infrastructure is most useful when the run context is inspectable as well as the device itself. Teams can connect their own fixture preparation and evaluation workflows to physical execution, then preserve the relationship between the starting context, actions, observations, and outcome.

A repeatable mobile-agent run does not begin when the first tap occurs. It begins when the account, data, permission, and app state have been prepared and verified for the question the run is meant to answer.

References