skip to content

In Appium, what do shouldUseCompactResponses and elementResponseAttributes change?

level: middleimportance: nice to knowfreq 28%

answer

  1. one shared name, two payloads
  2. find returns an identifier, nothing more
  3. attributes can ride along instead
  4. the list must be per-platform

basics

~20 s

Both settings control how much of an element comes back with a find. In compact mode the reply carries only the element identifier, so every attribute costs its own request; turning it off makes the driver inline the attributes named in elementResponseAttributes.

solid answer

~40 s

These two settings exist on **both** of Appium's native drivers — UiAutomator2 on Android and XCUITest on iOS — which makes them one of the few shared names in this area. In compact mode a find returns just the element identifier, and every fact you want about that element is a separate `GET /session/:sessionId/element/:elementId/attribute/:name`. Switch `shouldUseCompactResponses` off and the driver inlines attributes with the find result; `elementResponseAttributes` names which ones ride along. The shared setting name does **not** buy you shared content: the names you can usefully list are still the per-platform vocabulary — `checked`, `enabled`, `displayed`, `bounds` on Android, `value`, `label`, `visible`, `hittable` on iOS. For a milk-round app listing forty crate rows, that difference is dozens of round trips.

go deeper

for a junior

Be ready to say that a find normally returns only an element identifier, and that each attribute you then want is its own request to the Appium server.

for a middle

Explain the pairing: shouldUseCompactResponses decides whether attributes are inlined at all, and elementResponseAttributes decides which ones, on both the UiAutomator2 and XCUITest drivers.

for a senior

Show the diagnosis behind the tuning: a suite whose time scales with row count, and the judgement that it is a session-wide trade of payload size against round trips.

for a principal

Own the position that this is a performance lever with a correctness trap attached, since the shared setting name invites one shared attribute list that is wrong on both platforms.

## The problem these settings solve A milk-round delivery app shows tonight's round as a list of crate rows, and a test wants three facts about each row: is the *skip tomorrow* switch on, is the row drawn, and what does it say. Read the obvious way, each fact is its own request. `GET /session/:sessionId/element/:elementId/attribute/:name` takes a **single** name in its last segment, so three facts about one element are three HTTP round trips to the Appium server, which then talks to the on-device agent for each one. Across forty rows that is a hundred and twenty exchanges to answer a question a human answers by glancing at the screen. Both native drivers offer a way to compress that, and unusually for this tree they spell it the same way on both platforms. ## What each setting does - `shouldUseCompactResponses` — chooses how much of an element the driver serialises when it returns one. In compact form the reply carries essentially the element identifier and nothing else, which is the smallest payload and the reason a follow-up attribute read is needed at all. - `elementResponseAttributes` — the list of attribute names the driver should include when it is *not* being compact. It is the knob that decides which facts travel with the element instead of costing a request each. Used together the pattern is: turn compact responses off, name the attributes your assertions actually read, and let a find hand back the element plus its facts in one exchange. ## The same setting name, two different payloads This is where the platform honesty matters. Both the **UiAutomator2** driver on Android and the **XCUITest** driver on iOS declare `shouldUseCompactResponses` and `elementResponseAttributes`. That shared spelling is easy to misread as a shared feature with shared content. It is not. What you can usefully list is still each platform's own vocabulary: | | Android — UiAutomator2 driver | iOS — XCUITest driver | | --- | --- | --- | | Setting names | `shouldUseCompactResponses`, `elementResponseAttributes` | `shouldUseCompactResponses`, `elementResponseAttributes` | | Names worth listing | `checked`, `enabled`, `displayed`, `bounds` | `value`, `label`, `visible`, `hittable` | | Switch state arrives as | `true` / `false` under `checked` | `1` / `0` under `value` | So a configuration block that sets `elementResponseAttributes` to one shared list and sends it to both drivers is a configuration bug wearing the costume of a cross-platform setting. The Android list has to name Android's attributes and the iOS list has to name iOS's, exactly as the per-element reads would have had to. ## When to reach for it, and when not to 1. **Reach for it** when a test reads several attributes off many elements in one screen — a list assertion, a table check, a sweep over rows. 2. **Reach for it** when the round trips, not the app, are what make a test slow: the symptom is a test whose wall-clock time scales with row count rather than with anything the user would notice. 3. **Leave it alone** when a test reads one attribute off one element. The compact reply plus one attribute read is already two exchanges; inlining saves nothing and makes every unrelated find heavier. 4. **Leave it alone** if you cannot say which attributes you need. Listing everything you might want makes every element response larger for the whole session, including the finds that wanted only an identifier. ## The trade-offs to say out loud - It is a **session-wide** choice, not a per-call one: every element the driver returns pays the chosen shape, not just the ones your fast test cared about. - Bigger element payloads mean more to serialise on the device, more to send, and more to parse — the saving is in round trips, so it only wins when round trips were the cost. - The inlined values are the same values the per-name read would have given you, in the same per-platform vocabulary, so nothing about normalising them changes: a switch still arrives as `true` on Android and as `1` on iOS, and still needs turning into a boolean before an assertion sees it. - Because the two settings are declared per driver, an assertion helper that reads a name absent from the configured list quietly falls back to costing a request, so a suite can lose the optimisation without any error appearing. The reason this is worth knowing at all is diagnostic. When someone reports that a list-heavy Appium suite got dramatically slower after a refactor, the usual cause is not the app and not the locators — it is that the number of attribute reads per screen went up, and these two settings are the lever that decides what each of those reads costs.

  • Why can one shared elementResponseAttributes list not serve both drivers?
    Only the setting name is shared. The attribute vocabularies are not: Android's UiAutomator2 driver answers to `checked`, `enabled`, `displayed` and `bounds`, and iOS's XCUITest driver to `value`, `label`, `visible` and `hittable`. A shared list names attributes one platform does not carry, so it inflates payloads on both sides while inlining nothing useful on one.
  • What is the cost of turning compact responses off for a whole session?
    It is session-wide, so every element the driver returns carries the inlined attributes, including finds that only ever needed an identifier. You trade round trips for payload size and per-element serialisation, which pays off on list-heavy screens and loses on tests that find one element and act on it.

saying these in an interview costs you the question

  • Assumes a shared setting name implies a shared attribute list
  • Thinks one attribute request can return several names
  • Turns compact responses off globally to fix one slow test
  • Expects the inlined values to arrive already normalised
  • Confuses this with anything that changes the whole page source