Testing in app purchases is different from testing most features because you can't just tap button and see what happens. You need sandbox accounts that simulate purchases without real charges, test cards that trigger specific outcomes (success, failure, cancellation), and platform specific configuration in Google Play Console and App Store Connect. In this we covers both Platform .
Android: Google Play Billing sandbox setup
Google Play Billing uses license test accounts to simulate purchases without real charges. Here's setup.
Step 1: Configure in-app products in Google Play Console. Go to Monetization > Products > In-app products (or Subscriptions). Create your products with IDs that match your app's code (e.g., premium_monthly, coin_pack_100). Set pricing. Activate them.
Step 2: Upload a signed APK or AAB. Google Play Billing only works with signed builds. You don't need to roll out a release. Just upload signed build to a closed testing track. Wait a few minutes for it to process.
Step 3: Add license test accounts. Go to Settings > License testing. Add Google accounts that will test purchases. These accounts can make purchases without being charged. The purchase flow looks identical to a real purchase, but card is never billed.
Step 4: Test on a real device. This is part most teams miss: Google Play Billing doesn't work on emulators. You need a real Android device, signed into Play Store with a license test account. The device must have a PIN set (without one, subscription purchases can fail with a vague "Something went wrong" error).
Static responses for edge cases. Google provides reserved product IDs for testing specific outcomes without going through full billing flow: android.test.purchased (always succeeds), android.test.canceled (always cancels), android.test.item_unavailable (item not found). Use these to test how your app handles each response code.
iOS: StoreKit sandbox and Xcode local testing
Apple offers two testing environments: StoreKit Testing in Xcode (local, no server needed) and App Store sandbox (real server, real receipts).
StoreKit Testing in Xcode (local). Add a StoreKit Configuration file to your Xcode project (File > New > File > StoreKit Configuration). Define your products (subscriptions, consumables, non-consumables) with product IDs matching your app's code. Run app in Simulator or on a device. Purchases go through locally without connecting to App Store servers. You can simulate refunds, subscription renewals, interrupted purchases, and "Ask to Buy" flows directly from Xcode's Debug menu.
This is fastest way to test IAP during development. No Apple Developer account needed for local testing.
App Store sandbox (server-based). For testing with real App Store receipt validation, use sandbox accounts. Go to App Store Connect > Users and Access > Sandbox Testers. Create a test account with a fake email. On your iOS device, go to Settings > App Store > Sandbox Account and sign in with test account. Purchases made with this account are simulated (no real charges) but go through Apple's servers and generate real receipts.
Sandbox subscriptions renew on an accelerated schedule: a 1-month subscription renews every 5 minutes, a 1-year subscription renews every 1 hour. This lets you test renewal flows without waiting an actual month.
12 test scenarios for in-app purchases
These cover cases that break in production. They apply to both Android and iOS unless noted.
Happy path:
- Verify that a first-time user can complete a one-time purchase and content unlocks immediately
- Verify that a subscription purchase shows correct price, billing period, and trial duration before confirmation
- Verify that after a successful purchase, app reflects purchased state (premium badge visible, ads removed, content accessible)
Payment failures: 4. Verify that when payment is declined, app shows a clear error and doesn't unlock content 5. Verify that when user cancels mid-purchase (taps "Cancel" on Google/Apple payment sheet), app returns to previous screen without state changes 6. Verify that a network timeout during payment doesn't result in a charge without content delivery ("took money but didn't unlock" bug)
Subscription lifecycle: 7. Verify that a subscription renewal processes correctly and user retains access (test with sandbox's accelerated renewal) 8. Verify that when a user cancels a subscription, they retain access until end of current billing period 9. Verify that an expired subscription revokes access and shows an appropriate "Renew" prompt 10. Verify that upgrading from a monthly to an annual plan processes prorated difference correctly
Restore and cross-device: 11. Verify that "Restore Purchases" retrieves all previous purchases on a new device or after a reinstall 12. Verify that a subscription purchased on one device (e.g., iPhone) is accessible on another device (e.g., iPad) signed into same Apple ID or Google account
For how to document these as structured test cases, see our test case template.
The bugs that reach production
These are IAP bugs that generate most support tickets and 1-star reviews. If your testing covers nothing else, cover these.
"I paid but nothing happened." The payment API returns success, but app fails to acknowledge purchase or unlock content. This happens when purchase acknowledgment step is missing or fails silently. On Android, Google Play Billing requires you to call acknowledgePurchase() within 3 days or purchase is automatically refunded. On iOS, transaction must be finished (transaction.finish() in StoreKit 2) or it remains in queue and blocks future purchases.
Double charges on retry. The user taps "Buy," payment spinner hangs, they tap again, and two charges appear. This happens when app doesn't prevent duplicate purchase requests while one is in flight. The fix is disabling purchase button during processing and checking for existing pending transactions before initiating a new one.
Subscription shows as active after cancellation. The user cancels in Google Play or App Store settings, but app still shows them as subscribed. This happens when app checks local purchase state (cached) instead of validating against server (current). The fix is server-side receipt validation on every app launch, not just at purchase time.
"Restore Purchases" does nothing. Users reinstall app or switch devices, tap Restore, and nothing happens. On iOS, this is often caused by not calling AppStore.sync() in StoreKit 2 or not handling restoredCompletedTransactions callback in original StoreKit. On Android, queryPurchasesAsync() must be called at app launch to check for existing entitlements.
How to automate IAP testing
In-app purchase testing is hard to fully automate because Google and Apple payment sheets are system-level UI that most automation tools can't interact with. The payment sheet is rendered by OS, not by your app. Appium can't tap into it. Espresso can't reach it. XCUITest has limited support for interacting with system alerts but not full payment sheet.
There are two practical approaches:
Automate everything up to payment sheet. Automate flow from app's purchase screen to point where payment sheet appears. Validate that correct product name, price, and billing period are displayed on YOUR app's screen before system sheet opens. Then validate post-purchase state: is content unlocked? Is premium badge visible? Is receipt valid?
With Drizz, this works naturally. The test navigates to subscription screen ("Tap 'Go Premium,' validate '$9.99/month' is visible, validate 'Start Free Trial' button is visible"), and after purchase is completed (manually or via sandbox auto-approval), test validates post-purchase state ("Validate 'Premium' badge is visible, validate ads are not present"). Vision AI reads screen to confirm purchase state on real devices across Samsung, Pixel, and iPhone.
Use StoreKit local testing for iOS automation. Xcode's StoreKit Configuration file supports automated testing. You can trigger purchases programmatically without payment sheet appearing. This works for unit and integration tests inside Xcode but doesn't validate real payment flow.
For both approaches, critical tests to automate are: pre-purchase screen validation (correct price, product name, trial info) and post-purchase state validation (content unlocked, receipt stored, UI updated). The payment sheet interaction itself stays manual or uses sandbox auto-approval.
FAQ
Can I test in-app purchases on an emulator?
On Android, no. Google Play Billing requires a real device signed into Play Store with a license test account. On iOS, StoreKit local testing works in Simulator, but sandbox testing with real receipts requires a physical device or TestFlight build.
Do test purchases charge real money?
No. License test accounts on Android and sandbox accounts on iOS simulate full purchase flow without billing. The UI looks identical to a real purchase, but no card is charged.
How do I test subscription renewals without waiting a month?
Use App Store sandbox. Sandbox subscriptions renew on an accelerated schedule: 1-month subs renew every 5 minutes, 1-year subs renew every hour. On Android, use test subscriptions in closed testing track with Google-specified renewal acceleration.
What's most common in-app purchase bug?
"I paid but nothing happened." The payment goes through but app fails to acknowledge purchase or unlock content. On Android, unacknowledged purchases are auto-refunded after 3 days. On iOS, unfinished transactions block future purchases.
Can Drizz automate in-app purchase testing?
Drizz automates everything around purchase: navigating to subscription screen, validating price and product info, and verifying post-purchase state (premium badge, content access, ad removal). The system-level payment sheet interaction itself stays manual or uses sandbox auto-approval.
Should I test in-app purchases on every build?
Test full purchase flow before every release. On every build, automate pre-purchase validation (correct price displayed, purchase button present) and post-purchase state check (content unlocked after a sandbox purchase). This catches UI regressions without re-running full payment flow each time.


