How to Test SMS and OTP Codes on iOS (and Android)
How to test OTP codes and SMS on iPhone and Android: AutoFill, the iOS Simulator's limits, sending SMS from code, and delivery tests on real devices.
Short answer: To test an SMS OTP on iPhone, mark the code field .oneTimeCode, request a code on a real phone and confirm AutoFill fills it. Then check four things. The code arrives once, from the right sender. It fills in: through the AutoFill suggestion above the keyboard on iPhone (textContentType = .oneTimeCode), and through the SMS Retriever API or manual entry on Android. Wrong, expired and resent codes behave correctly. Any link in the message opens the right screen. The iOS Simulator can't receive a carrier SMS, so use it for code-entry and validation logic, then confirm delivery and AutoFill on real devices with active SIMs.
| # | Test case | Expected result |
|---|---|---|
| 1 | Request a code on a real number | One SMS arrives with the correct sender and code |
| 2 | Tap the code suggestion above the keyboard (iOS) | The code fills the field; sign-in continues |
| 3 | Enter an expired code, then tap Resend | Clear error; the new code works and the old one is rejected |
| 4 | Tap the link in the SMS (app installed / not installed) | App opens to the right screen / website loads |
| 5 | Repeat on a second carrier and an international number | Same results, with correct formatting and language |
How do you test OTP codes on iPhone?
On iOS, a code from Messages appears above the keyboard when the text field is marked as a one-time code field (Apple: oneTimeCode; Apple: Enabling Password AutoFill on a text input view):
codeTextField.textContentType = .oneTimeCode
Test cases:
- The suggestion appears when the field is focused, and tapping it fills the full code.
- A split code field (one box per digit) still receives the full code.
- Paste works, and typing by hand works.
- With two codes received close together, the app accepts only the code it should.
These checks need a real iPhone that receives the SMS.
How do you test OTP codes on Android?
Android apps often use the SMS Retriever API to read a verification SMS automatically (Android: Request SMS verification). Your app calls startSmsRetriever(), which waits for one matching message for up to five minutes. The message has to contain a string that identifies your app. Test cases:
- A message containing the app's identifying string is picked up and the code is filled in.
- A message without the string, or sent with the wrong string by a debug build, is ignored, and manual entry still works.
- A message that arrives after the five-minute wait has ended. The app should offer Resend or manual entry.
- Release and debug builds both work. Confirm your server sends the identifying string that matches each build you ship.
Can you test SMS or OTP in the iOS Simulator?
No. The Simulator isn't a phone on a carrier network, so a carrier SMS can't reach it. Use it to unit-test your code-parsing and validation logic, and use XCTest UI tests (Apple: XCTest) to check the code screen with a value your test backend accepts. Then confirm delivery and AutoFill on a real phone.
What should you test in an SMS flow?
- Delivery: the message arrives, the sender ID is the expected one, and there are no duplicates.
- Content: the code length and format, the brand name, any variables filled in, and a message length that doesn't split awkwardly.
- Code entry: AutoFill, paste and manual typing all work. Entering a wrong code shows an error.
- Expiry and resend: expired codes are rejected, Resend is rate-limited, and only the newest code is accepted if that's your rule.
- Links: any URL in the message opens the app or the website correctly. See our Universal Links guide.
- Interruptions: the person backgrounds the app to open Messages and then comes back. The code screen should still be there. See backgrounding.
How do you send an SMS from code in iOS (Swift / Objective-C)?
iOS has no API that sends an SMS silently from your app. MFMessageComposeViewController presents the standard compose screen with the recipients and body you fill in. The person can edit the message and then sends or cancels it, and the Messages app does the sending (Apple: MFMessageComposeViewController). So a test of "send SMS from code" on iOS is really a test of that compose screen:
guard MFMessageComposeViewController.canSendText() else { return } // hide or disable the feature
let composeVC = MFMessageComposeViewController()
composeVC.messageComposeDelegate = self
composeVC.recipients = ["4085551212"]
composeVC.body = "Your invite link: https://example.com/i/abc"
present(composeVC, animated: true)
The Objective-C version uses the same class ([MFMessageComposeViewController canSendText]). Test these cases:
canSendText()returnsfalse(for example, a device that isn't set up for messaging). The app should hide or disable the feature instead of presenting the composer.- Prefilled recipients and body are correct and can still be edited.
- Attachments and subject: check
canSendAttachments()andcanSendSubject()before using them. - Cancel and Send both dismiss the composer. Your delegate must dismiss it in
messageComposeViewController(_:didFinishWith:), so test both results. - No delivery assumption. Apple notes the composer doesn't guarantee delivery. The Messages app takes over sending, so don't mark an invite as "delivered" just because the person tapped Send.
An alternative is an sms: URL, which opens the Messages app directly. Test that path separately.
For test messages your backend sends to a phone, such as OTPs and alerts, use your SMS provider's API from the server side, and test the result on the phone as described above.
How do you test SMS delivery across carriers and countries?
Carrier and route differences cause many SMS failures that only reach production. Cover the following:
- At least two carriers in your main market.
- International numbers, including the country-code entry and formatting in your UI.
- Localized message templates, if you send them.
- Numbers ported between carriers, and eSIM lines, if your users have them.
- Sender ID type, such as a short code, a long number or an alphanumeric sender, wherever your SMS provider uses different routes.
Record the device, carrier, OS version and the message as received for every failure.
How do you test a link inside an SMS?
Treat it like any other deep link:
- App installed and logged in: the link opens the target screen.
- App installed and logged out: the person signs in, then continues to the target.
- App not installed: the website or App Store fallback appears. If you route new installs after install, see deferred deep links.
- Check that the link isn't broken by URL shortening or by the message splitting into parts.
How does Mobot test SMS and OTP flows?
Mobot runs SMS and OTP flows on real iPhones and Android phones, tapped by physical robots. That covers requesting the code, using the AutoFill suggestion, tapping links in Messages, and switching between apps. Mobot AI and Mobot's team build your test cases from your sign-in and verification flows. Every defect report includes device screenshots of each step.
FAQ
How do you test SMS OTP codes on iPhone?
Set the code field's textContentType to .oneTimeCode. Then, on a real iPhone, request a code and confirm the suggestion appears above the keyboard and fills the full code. Also test paste, manual entry, expiry and resend.
Is there an SMS simulator for iOS testing? The iOS Simulator can't receive carrier SMS. Use it to test your code-entry screen and validation logic with a code your test backend accepts, then test real delivery and AutoFill on a phone with an active SIM.
Can you send an SMS from code on iOS without the user?
No. MFMessageComposeViewController only presents a prefilled message for the person to approve, and the Messages app sends it. Check canSendText() first, and send server-side messages such as OTPs through your SMS provider.
How do you test SMS delivery across carriers? Send the same message to numbers on at least two carriers and to international numbers. Then compare arrival, the sender ID, the formatting and whether the code works on each.
How do you test a link inside an SMS? Tap it with the app installed and logged in, installed and logged out, and not installed. Confirm each case opens the right screen or falls back to the right page.