How to Test OTP Flows in Staging Without Real SIM Cards
Anyone who has tested a sign-up flow knows the pain: every run needs a fresh phone number, someone has to read the SMS, and the team's personal SIMs end up on marketing lists. A better way to test OTP flows in staging without real SIM cards is to separate what you test from what you use.
Short answer: in your own staging environment, use a configurable bypass or a fixed test code so most runs need no SMS at all. Reserve a small number of end-to-end runs with real delivery, and get the numbers for those from a service you can call from code.
Three layers of OTP testing
| Layer | What it checks | SMS needed? |
|---|---|---|
| Unit tests | Code generation, expiry, retry limits | No |
| Staging with a test code | Screens, redirects, errors | No, use a fixed code you control |
| End-to-end with real delivery | The SMS provider, formatting, delay | Yes, a few runs only |
What to test on every OTP screen
- Correct code accepted, wrong code rejected with a clear message.
- Expired code rejected.
- Resend timer and retry limits.
- Number format and country code handling.
- Rate limiting and lockout messages.
- Accessibility of the input field, including paste and autofill.
Getting numbers for end-to-end runs
For real-delivery runs, order a number through an API, trigger the SMS from your staging app, read the code in your script and finish the order. See the examples in Python, PHP and Node.js.
Rules for responsible testing
- Test only systems you own or are allowed to test.
- Never use real customers' data in staging.
- Do not use these numbers to evade another service's limits.
- Cancel orders that time out and track the cost per run.
Keeping cost under control
Pay-per-use pricing means a small suite costs only what it uses. Use rentals only when a test needs the same number across several days, and read the pricing page for how it works.
A sample test plan
- Unit tests for generation, expiry and retry counters.
- Staging tests with a fixed code for every screen and error message.
- One end-to-end test per country you support, using a real number and a real SMS.
- A weekly smoke test that sends one real SMS and checks the delay.
- An alert if the delay passes your target.
This keeps real SMS costs small while still catching provider outages early.
Metrics worth tracking
- Median and slowest delivery time per country.
- Share of codes that never arrive.
- Number of resend taps per successful sign-up.
- Error rates on the OTP screen.
When a metric moves, you will see it before your users complain. These numbers also help you decide whether to change provider or add a voice fallback.
Working with a team
Agree on who owns the SMS budget, how many real runs are allowed per day and where test results are stored. Give each tester an account that can be switched off when they leave. Share the log of order IDs so that a failed run can be traced. If several people test the same app, schedule the real-SMS runs so that they do not trigger the app's rate limits together. A little coordination turns a noisy, expensive routine into a quiet one.
Frequently Asked Questions
Should staging send real SMS?
Only for a few end-to-end checks. Most runs should use a fixed test code.
How do I stop test runs from messing up production metrics?
Use separate environments and tag test traffic.
Can I test several countries?
Yes. Choose the country when you order a number, and check number-format handling for each.
What if the code is delayed?
Set a timeout, cancel the order and record the delay as a result.
Conclusion
Keep most tests SMS-free and automate the few real ones. Create an account to try the API, and read more on the OtpGet blog.