skip to content

In an Appium fleet, how do you stop a degraded link on Android or iOS from outliving its session?

level: seniorimportance: should knowfreq 38%

answer

  1. device state, not test state
  2. restore in teardown, including on failure
  3. read the state back, do not assume
  4. pair enable with disable on Apple
  5. do not cut your own control channel

basics

~20 s

Undo it explicitly in teardown, on both paths. Android radios stay exactly as mobile: setConnectivity left them, so restore them and confirm with mobile: getConnectivity; on Apple hardware call mobile: disableConditionInducer. Do not assume deleting the session restores either.

solid answer

~40 s

Treat link degradation as device state you borrowed, not as a test step. On **Android**, `mobile: setConnectivity` changes the real device: radios you switched off are still off for whatever runs next, and an emulator keeps whatever `mobile: networkSpeed` set until it is rebooted. Restore in a teardown that also runs on failure, and verify with `mobile: getConnectivity` instead of trusting the write. On **Apple real devices**, pair every `mobile: enableConditionInducer` with `mobile: disableConditionInducer`, and call the disable defensively at session start too. Two hazards make this worse than ordinary cleanup: a device attached over Wi-Fi loses the very transport carrying your commands the moment you switch Wi-Fi off, and a shared device left disconnected looks like broken hardware to whoever picks it up next.

go deeper

for a junior

Know that these commands change the device itself: if a run switches Wi-Fi off with mobile: setConnectivity and never switches it back, the phone stays that way after the test process has exited.

for a middle

Explain the undo on each side — writing the flags back with mobile: setConnectivity and confirming with mobile: getConnectivity on Android, mobile: disableConditionInducer on Apple hardware — and why a recycled emulator keeps a networkSpeed profile.

for a senior

Demonstrate the operational habits: restore unconditionally, verify rather than assume, and recognise that a device left in airplane mode is reported as failing hardware by whoever picks it up next.

for a principal

Own the policy: whether degraded-link work gets dedicated targets or a mandatory pre-session reset, so one leaked setting cannot quietly poison every later run on the same device.

## Degradation is device state, not test state Most of what a test does dies with the session: the app is closed, the element cache is dropped, the driver goes away. Network degradation does not. `mobile: setConnectivity` writes to the device's radios and `mobile: enableConditionInducer` turns on a profile in the operating system, and both of those outlive the process that asked for them. On a laptop with one attached phone that is a nuisance; on a shared fleet it is a defect that shows up in someone else's run. ## Android: what stays behind On Android there are two separate leftovers, and they are cleaned differently. - **Radios**, set by `mobile: setConnectivity`. Nothing in the session teardown puts them back. If a parking-permit renewal case switched mobile data off to assert the queued-renewal notice and then failed the assertion, the device is still without data when the next session starts. - **Emulator link speed**, set by the emulator-only `mobile: networkSpeed`. A re-used emulator carries that profile forward; a freshly booted one does not, which is why the symptom looks intermittent on a pool that sometimes recycles instances. The read-back is what turns cleanup from hope into verification: `mobile: getConnectivity` reports the state the device is actually in. Assert on it after restoring, and the difference between a leaked setting and a genuinely sick device stops being guesswork. ## Apple: pair every enable with a disable On Apple real devices, `mobile: enableConditionInducer` has an explicit counterpart, `mobile: disableConditionInducer`. Call it. There are two places worth calling it from: 1. **Teardown**, unconditionally, so a failing assertion cannot skip it. 2. **Session start**, defensively, so a device abandoned mid-run by an earlier crash starts clean rather than inheriting a profile. `mobile: listConditionInducers` tells you what the device can impose, which is also how you avoid hardcoding an identifier that a given device does not offer. The one thing not to do is rely on the session ending as the cleanup mechanism — the run should undo what it did, on the same path where it did it. ## Do not cut the branch you are sitting on There is a hazard on this leaf that other environment controls do not have: **the degradation can sever your own control channel**. Appium commands reach the device over a host connection. If that connection runs over the network rather than a cable, switching Wi-Fi off with `mobile: setConnectivity` kills the transport the next command needed, and the session dies holding the device in the state you were about to undo. On a fleet, prefer wired attachment for cases that take the radios down, and if that is not possible, degrade something narrower than the radio your control path is using. ## Undo, side by side | Left behind | Android | Apple real device | |---|---|---| | what leaks | radio state, emulator link profile | an enabled condition profile | | the undo | write the flags back with `mobile: setConnectivity` | `mobile: disableConditionInducer` | | the check | `mobile: getConnectivity` | `mobile: listConditionInducers` before enabling | | clears on reboot | emulator profile does, handset radios do not | not something to rely on | ## A restore that actually runs The practices that separate a suite that leaks from one that does not are unglamorous: - Put the restore in unconditional teardown, never as the last line of the test body, so a throw cannot skip it. - Restore before you assert wherever the assertion does not need the link down. - Verify the restore rather than assuming the write landed. - Reset defensively at session start, because the previous run may have died before its own teardown. - Log the degraded window with timestamps, so a later failure on the same device can be traced to a leak instead of to hardware. ## The symptom to recognise The reason this is a senior question is the shape of the bug report it produces. Nobody reports a leaked setting. They report that a device in the pool is unreliable, that installs time out on it, or that one device fails cases the others pass. A device stuck in airplane mode or holding a condition profile presents exactly like failing hardware, and the fix is a teardown fifty lines away in a case that already passed. Knowing that these two commands write through to the device — and that Appium keeps no snapshot to roll back to — is what lets you look in the right place.

  • How do you tell a leaked network setting from genuinely broken device hardware in a fleet?
    Read or reset the state instead of guessing. On Android, `mobile: getConnectivity` reports the radios, so a device that behaves again after an explicit restore was leaking rather than failing. On an Apple real device, call `mobile: disableConditionInducer` at session start rather than trusting that the previous run cleaned up after itself.
  • Where should the restore live so it survives a failing assertion?
    In unconditional teardown around the case, not the last line of the test body. If the assertion throws while the link is down, a restore written after it never runs and the next session inherits the damage. The same applies to the Apple side: `mobile: disableConditionInducer` belongs where a failure cannot skip it.

saying these in an interview costs you the question

  • Assumes deleting the session restores connectivity
  • Restores the link only on the happy path
  • Leaves a condition inducer enabled on a shared iPhone
  • Switches Wi-Fi off on a device attached over Wi-Fi
  • Trusts the toggle instead of reading the state back
  • Blames the next run's failure on flaky hardware