SMS Verification Testing: A Step-by-Step Guide for QA Teams
How to test the OTP step in sign-up and login flows with real numbers: a QA checklist, key edge cases, API automation and protecting employee privacy.
Table of contents
Every app that verifies users with a one-time passcode (OTP) during sign-up, login or password reset has to make sure that step works under real-world conditions. Thorough SMS verification testing checks more than whether the code arrives; it also covers expired codes, resend limits and incorrect entries. In this article, we give QA teams and developers a practical test plan, the edge cases to watch for, and ways to automate the process.
Why test with real phone numbers?
Mock services that simulate your SMS provider in development give you fast feedback, but they don't reflect everything that happens in the real world. Carrier delays, different country codes, number formatting differences and how the message actually looks on a device can only be verified with a real number. Running your SMS verification testing with a real number in staging and before every launch helps you catch the problems your users would otherwise run into.
Using team members' personal phones for this is neither practical nor good for privacy. Test accounts tied to the number of an employee who leaves the team can also become inaccessible over time. Temporary virtual numbers are a clean way to keep test data separate from personal data. If the concept is new to you, read What is a virtual phone number?
SMS verification testing checklist
The list below can serve as a baseline test plan for most OTP flows:
- Does the phone number field correctly handle country codes and different formats (with spaces, with a leading zero, and so on)?
- Does the SMS arrive within a reasonable time, and is the message content clear?
- When the correct code is entered, does the flow move smoothly to the next step?
- Are the code's length, format and validity period consistent with the documented values?
- After a successful verification, is it impossible to reuse the same code?
- Do error messages guide the user without revealing unnecessary details about the system?
- Are phone numbers and codes masked in analytics tools and logs?
- Does the code input field work with copy-and-paste and with the device's code autofill feature?
Edge cases you should always test
Expired code
Enter the code after its validity period has ended. The system should reject it and clearly offer the user the option to request a new code.
Resending
Tap the "Resend code" button several times in a row. Check whether a cooldown is enforced and whether the old code becomes invalid when a new one is sent.
Wrong code
Enter an incorrect code a few times. When the attempt limit is exceeded, is the session temporarily locked, and is that clearly communicated to the user?
Different countries and number formats
If your app is used in more than one country, don't limit your tests to a single country code. Verify that number validation rules, the SMS template and character encoding work correctly across different country codes. In particular, make sure messages that contain accented or non-Latin characters don't appear garbled on some devices. Our virtual number country guide explains what to consider when picking test countries.
Rate limiting
Confirm that the system enforces a limit when many code requests are sent to the same number in a short period. This is an important security control that reduces both SMS costs and the risk of abuse.
The code never arrives
Test what your app does when the user can't receive the code: is there an alternative verification method, a support link, or clear guidance? For the most common causes on the user's side, see our article on not receiving an SMS verification code.
Automating tests with an API
Manual tests are fine at the start, but repeating the same steps by hand for every release during regression testing is inefficient. OnaySIM provides a personal API key that you can get from your profile, and its API is compatible with common SMS activation APIs. A typical automated test runs like this:
- The balance is checked at the start of the test.
- A number is requested for the relevant service and country.
- The test automation enters the number on your app's sign-up screen.
- The order status is polled at reasonable intervals until the code arrives.
- The received code is entered in the app and the result is verified.
- The order is completed, or canceled if no code arrives.
On OnaySIM, a number is reserved for about 20 minutes; if no code arrives within that window, the order is canceled and the charge is refunded to your balance. Set your test timeouts to fit this window. For details, see the API documentation, and use the IP allowlist in your profile to restrict API access to your CI servers only.
It also pays to log each test run's result, the code delivery time and any canceled orders. Over time, this shows you which scenarios are flaky and helps you separate failures caused by SMS delays from real bugs in your app.
Protect test data and employee privacy
- Keep test accounts separate: Mark accounts created for testing with a naming convention and never mix them with production data.
- Don't use personal numbers: Keep employees' personal numbers out of test databases, logs and screenshots. Our phone number privacy guide offers more ideas on this.
- Don't tie permanent accounts to virtual numbers: Virtual numbers are temporary; for shared accounts you'll need access to long term, use a permanent company number and additional recovery methods.
- Follow the rules: Comply with the Terms of Service of every service you interact with during testing, and never use your test infrastructure as a tool for creating accounts in bulk.
Conclusion
Well-planned SMS verification testing lets you catch the problems your users might face during sign-up and login before you go live. Add the checklist and edge cases to your test plan, automate repetitive scenarios with the API, and keep team members' personal numbers out of the process. To get started, create a free account, then run your first test from the get a number page.


