Drizz raises $2.7M in seed funding •
Featured on Forbes
Drizz raises $2.7M in seed funding •
Featured on Forbes
Logo
Blog page
>
Interrupt Testing for Mobile: Calls, Alerts, Network Drops

Interrupt Testing for Mobile: Calls, Alerts, Network Drops

Interrupt testing for mobile apps. iOS vs Android lifecycle differences, real simulation commands, and interrupts most teams skip.
Author:
Partha Sarathi Mohanty
Posted on:
July 3, 2026
Read time:

Key takeaways

  • Interrupt testing on mobile means verifying your app survives external events (phone calls, alerts, notifications, network drops, background transitions) without crashing or losing state.
  • The interrupt type matters less than state you're in when it happens. A phone call during idle is nothing. A phone call during a payment confirmation is bug.
  • Most posts list interrupt types. Almost none show you how to actually trigger them in tests. This one does, for both iOS and Android, with commands.

Interrupt testing on mobile is practice of testing how your app handles external events that pause or preempt it. Incoming calls. Push notifications from other apps. System dialogs like "Save password to Keychain." Low battery warnings. Network drops. Screen locks.

Every generic post lists these categories and stops. The real value is in details: what breaks, on which platform, when interrupt fires during a critical flow. That's what this post covers.

What interrupt testing actually is

Interrupt testing verifies that your mobile app can handle unplanned pauses without crashing, losing user data, or ending up in a broken state on resume. The app doesn't need to keep running through interrupt. It just needs to come back correctly.

The four correct outcomes an app can produce after an interrupt:

  1. Run in background. App yields to interrupt, continues running behind it, resumes on top when interrupt ends. This is what a music player does during a call.
  2. Pause and resume. App suspends, restores when foregrounded. Most apps do this.
  3. Show inline alert. App keeps running, displays interrupt as a banner. Notifications typically work this way.
  4. No impact. App ignores event entirely. Battery charging notifications for a non-battery app.

Any other outcome is a bug. Crash. Lost data. Broken UI. Frozen state. Wrong screen on resume.

Phone calls, alerts, and background transitions are core to any iOS test plan, which is where interrupt testing fits into broader iOS QA workflow.

Not all interrupts are equal

Every checklist online groups interrupts by source: calls, SMS, notifications, alarms, low battery. That grouping isn't useful for testing.

Better framing: group by state loss risk when interrupt fires.

Zero-risk interrupts. App is idle on home screen. Someone taps notification. Nothing to lose. Test these quickly, move on.

Low-risk interrupts. App is on a static screen, no ongoing operation. Interrupt fires, app pauses, comes back on same screen. Basic lifecycle test.

Medium-risk interrupts. App is doing something (loading data, playing video). Interrupt fires. On resume, app needs to pick up correctly. Common failure: video plays audio but not video, or restarts from beginning.

High-risk interrupts. App is mid-payment, mid-checkout, mid-upload. Interrupt fires. This is where double-charge, lost-order, and duplicated-write bugs happen. Test these hardest.

Catastrophic-risk interrupts. The OS killed your app in background during a critical operation. This is one nobody tests until a user complains their order disappeared. Test it.

Your interrupt test plan should prioritize by risk, not by interrupt type. Testing "receive SMS" 30 times across every screen is a waste. Testing "OS killed app during payment processing" once is where you find real bugs.

Tests that pass at desk and fail in CI often fail because of missed interrupt testing coverage on risky interrupts. The CI environment has different memory pressure, different network timing, and different interrupt firing than a QA lead's local device.

iOS interrupt handling

iOS has a fairly clean lifecycle. Your UIApplicationDelegate gets:

  • applicationWillResignActive when an interrupt is about to take focus
  • applicationDidEnterBackground when app is fully backgrounded
  • applicationWillEnterForeground when returning
  • applicationDidBecomeActive when active again

Real interrupts and what fires:

  • Phone call: willResignActive fires when call arrives. didEnterBackground fires only if user answers.
  • Push notification banner: willResignActive fires. didEnterBackground fires only if user taps notification.
  • Face ID system dialog: willResignActive fires but app stays on screen.
  • OS "Rate this app" dialog: same as Face ID.
  • Low battery: no lifecycle event by default. You subscribe to NSProcessInfoPowerStateDidChangeNotification if you care.
  • Airplane mode toggle: no lifecycle event. You subscribe to network reachability.

The subtle one: applicationWillResignActive fires for lots of things that don't fully background you. Your code shouldn't assume app is backgrounded just because willResignActive fired. If you save critical state there, you're saving too often. If you don't save until didEnterBackground, you might lose state on a Face ID dialog.

For Apple's official app lifecycle documentation covers each callback in detail if you need exact firing order for a specific scenario.

Android interrupt handling

Android's lifecycle is messier. Every Activity (or Fragment) sees:

  • onPause when losing foreground
  • onStop when no longer visible
  • onDestroy when activity is destroyed
  • onResume on return
  • onRestart when returning from onStop

Plus for whole app: onTrimMemory (with different levels), and Application lifecycle callbacks.

Real interrupts and what fires:

  • Phone call: onPause fires when call UI arrives. onStop fires if user answers.
  • Notification pull-down: onPause fires. onResume when they dismiss.
  • Permission request dialog: onPause fires.
  • System alerts (low battery, OS update available): onPause fires.
  • Configuration change like screen rotation: onDestroy then onCreate unless you handle it.
  • App killed for memory: onTrimMemory(TRIM_MEMORY_COMPLETE) fires first, then eventually your process dies. When user comes back, onCreate runs fresh with a savedInstanceState bundle if you saved one.

Interrupt testing on Android covers system dialogs, incoming calls, and permission prompts, and each one has different lifecycle callbacks that fire. If your state restoration code assumes onPause = onSaveInstanceState gets called, you're going to lose data in some cases where it doesn't.

The trickiest Android interrupt to test is "app killed by LMKD" case. The OS killed your background process because memory pressure was high. When user returns, process starts fresh. If you weren't persisting state to disk (or restoring from a Bundle), everything is gone. Users see a blank home screen. They think app is broken. It technically worked as designed.

How to actually simulate interrupts in tests

Every generic post says "simulate an interrupt." Almost none show how. Here's shortlist.

iOS Simulator:

# Simulate low memory warning
xcrun simctl push booted com.your.bundle payload.json

# Trigger memory warning
xcrun simctl notify_post com.apple.system.lowmem

Physical iOS device:

  • Phone calls: actually make one from another device, or use Simulator's "Simulate Incoming Call" menu (available since Xcode 15)
  • Push notifications: send from your APNS backend
  • Background/foreground: xcrun devicectl commands can drive it

Android emulator (adb):

# Simulate incoming call
adb emu gsm call +15555551234

# End the call
adb emu gsm cancel +15555551234

# Simulate SMS arrival
adb emu sms send +15555551234 "test message"

# Simulate low battery
adb shell dumpsys battery set level 15
adb shell dumpsys battery set status 3

# Kill app process (simulates OS kill)
adb shell am kill com.your.app

Physical Android device:

  • Actual calls: yes, make one
  • Notifications: from your backend or via adb shell am broadcast
  • Process kill: adb shell am kill com.your.app works on physical devices too

These commands go directly into your test script. Set up state you want to test. Fire command. Wait. Verify.

Interrupt testing gaps that cause bugs

Four scenarios I see teams skip that consistently ship bugs.

Interrupt during a network request. User taps "Submit order." Request is in flight. Phone rings. User answers. Comes back after 4 minutes. What state is app in? Did request complete? Did you retry? Did you show a stale spinner? Test this.

Interrupt during camera or biometric flow. User is scanning a document. Notification arrives. Camera preview pauses. Notification dismisses. Camera preview needs to resume, and preview session needs to still be valid. On both platforms this is a well-known source of camera bugs.

Two interrupts in a row. OS update prompt appears. User dismisses it. Push notification arrives immediately. Your app just saw two lifecycle transitions in 200ms. State machines that assume one transition at a time break here.

Backgrounded then killed then relaunched from a deep link. User backgrounds your app. OS kills it. Push notification arrives 5 minutes later. User taps it. App relaunches into a deep link destination. State restoration is doing three jobs at once: cold start, deep link routing, and stale-session handling. This is where "app crashed on notification tap" bugs come from.

Where selector-based frameworks fail on interrupts

Selector-based tools (Appium, XCUITest, Espresso) struggle with interrupts for two specific reasons.

System dialogs cover your locators. When iOS shows "Save password?" dialog on top of your app, your test's findElementByAccessibilityId returns nothing because your app isn't on top window anymore. The test throws NoSuchElementException. The test failure looks like a product bug. It's not. The test just didn't handle system dialog.

Some frameworks (XCTest, Espresso) let you register interrupt handlers explicitly. UIInterruptionMonitor on iOS. UiDevice on Android. These help, but only for interrupts you anticipated. The unanticipated ones break your test suite.

Test state gets corrupted by interrupt timing. Your test taps "Submit." The click happens 200ms before an unrelated system notification lands (because your test device happened to sync mail at that moment). Test fails. Nothing product-related happened.

The fix in most selector frameworks is defensive coding for every possible interrupt at every step. That's a lot of code to maintain and it still doesn't cover everything.

What works for interrupt testing at scale

We built Drizz partly for this shape of problem. Vision AI reads screen way a person does. When a system dialog appears on top of your app, Vision AI sees both dialog and, if instructed, dismisses it, then proceeds with test. When a notification banner lands during a test step, Vision AI recognizes it as a banner (not part of app UI) and can be told to ignore it. No locator to break. No exception to catch.

Before-and-after on "user makes a payment while a system notification arrives" test.

Before, on Appium: Test taps "Pay now" at exactly 3:47pm. Push notification from another app lands at 3:47:01pm. Notification banner covers "Payment processing" spinner. Appium's locator for spinner times out. Test fails as "spinner not found." QA lead investigates for 30 minutes. Nothing wrong with app. Rewrites test to explicitly dismiss any notification banner that might appear. Two sprints later, a different notification banner style breaks dismiss logic. Cycle repeats.

After, on Drizz: Same test, plain English. Tap "Pay now". Validate "Payment processing" is visible. When notification banner appears, Vision AI sees "Payment processing" spinner behind it. Test passes. If test author wants to explicitly handle banner, Dismiss notification banner in plain English does it.

For interrupt testing specifically, this matters because interrupts are inherently unpredictable. Coding against every possible one is a losing battle in a selector framework. Vision AI handles them because it's looking at screen state, not at a locator hierarchy.

FAQ

What is interrupt testing in mobile apps?

Testing how the app handles external events like calls, notifications, alerts, and network drops without crashing or losing state.

What's the difference between interrupt testing and recovery testing?

Interrupt testing checks handling of external events. Recovery testing checks handling of failures like crashes or hardware issues.

How do you simulate interrupts in mobile testing?

Use adb commands for Android and xcrun simctl for iOS simulator.Simulator. Physical devices need real events triggered manually.

Which interrupts should be tested first?

The ones with highest state-loss risk. Payment flows, uploads, and mid-transaction operations. Not idle-state interrupt tests.

Can interrupt tests be automated on real devices?

Yes, but selector-based frameworks flake on system dialogs. Vision-based frameworks handle unexpected dialogs and banners more reliably.

How is iOS interrupt handling different from Android?

iOS has a cleaner lifecycle with fewer callbacks. Android has more edge cases, especially around memory-related process kills.

About the Author:

Partha Sarathi Mohanty
Co-founder & CPO, Drizz
ISB-trained product leader with battle scars from Mensa, Zolo, BlackBuck, and Shadowfax, now turning AI-native testing into an actual roadmap.
Schedule a demo