How to Write Test Cases for OTP Verification (With Examples)

How to Write Test Cases for Otp Verification (With Examples) begins with a clear grasp of the OTP flow and ends with a reusable test matrix.

April 23, 2026 · 15 min read · How-To Guides

How to Write Test Cases for Otp Verification (With Examples) begins with a clear grasp of the OTP flow and ends with a reusable test matrix.

This guide walks you through every step needed to design high‑signal test cases for one‑time password verification, from flow analysis to traceability, and shows how manual design pairs with autonomous exploration to achieve real coverage.

Understanding OTP Verification Flow

Before writing any test case, map the end‑to‑end process that the system follows when a user requests and validates an OTP. A typical flow includes:

  1. Trigger – user clicks “Send OTP” or system initiates verification (e.g., login, password reset, payment).
  2. Request Generation – backend creates a random numeric or alphanumeric code, stores it with expiry timestamp and usage limit, and dispatches it via SMS, email, push, or voice.
  3. Delivery – the user receives the code through the chosen channel.
  4. Input – user enters the code into the UI field.
  5. Validation – backend checks code correctness, expiry, and reuse constraints; returns success or failure response.
  6. Post‑validation Action – on success, the system proceeds to the protected operation (e.g., grants access, resets password); on failure, it shows an error and may allow retries.

Identify all touchpoints where variations can occur: channel latency, code format, resend limits, brute‑force protection, accessibility of the input field, and handling of expired or already‑used codes.

Why Flow Mapping Matters

A test case that only checks “correct code → success” misses failure modes that appear only when a preceding step behaves unexpectedly. By documenting each step, you can derive preconditions, inputs, and expected results that target specific risks.

Anatomy of a Robust Test Case

A well‑structured test case contains the following elements:

ElementDescriptionExample for OTP
IDUnique identifier (e.g., OTP‑001)OTP‑001
TitleShort, readable summary“Valid OTP entered within expiry leads to successful login”
PreconditionsState that must be true before executionUser is on login screen, phone number verified, OTP service configured
StepsNumbered actions performed by tester or script1. Tap “Send OTP”. 2. Wait for SMS. 3. Enter 6‑digit code. 4. Tap “Verify”.
Test DataSpecific values usedCode = 123456, expiry = 120 s
Expected ResultObservable outcomeSystem navigates to home screen, shows welcome toast
PostconditionsSystem state after test (if needed)Session token stored, user authenticated
PriorityP0‑P3 based on riskP0
TraceabilityLink to requirement or user storyREQ‑OTP‑01, REQ‑OTP‑07

Each element forces you to think about what you are validating and makes the case reusable across manual and automated suites.

Writing Steps That Are Automation‑Friendly

Use imperative language that maps directly to UI actions or API calls. Avoid vague phrasing like “check that the OTP works”. Instead, write:

When steps are precise, test engineers can translate them into Appium, Playwright, or Selenium scripts with minimal interpretation.

Positive Test Cases for OTP Verification

Positive cases verify that the system behaves correctly when everything works as intended. Below is a representative set; you can expand based on channel specifics.

IDPreconditionsStepsExpected Result
OTP‑POS‑01User on login screen, valid phone number registered1. Tap “Send OTP”. 2. Receive SMS with code 654321. 3. Enter 654321. 4. Tap Verify.System logs user in, redirects to dashboard, shows success toast.
OTP‑POS‑02User requesting password reset, email verified1. Click “Forgot Password”. 2. Enter email, tap Send OTP. 3. Receive email with code 987654. 4. Input code, tap Verify. 5. Enter new password, tap Submit.Password updated, user prompted to log in with new credentials.
OTP‑POS‑03User performing a payment, OTP via push notification1. Add item to cart, proceed to checkout. 2. Choose credit card, tap Pay. 3. Receive push OTP 123‑456. 4. Enter code, tap Confirm.Payment authorized, order confirmation page shown, email receipt sent.
OTP‑POS‑04User enrolling a new device, OTP via voice call1. In Settings, tap “Add Device”. 2. Choose voice call, enter phone number. 3. Receive call, hear spoken code 321098. 4. Enter code, tap Verify.Device added, appears in device list, session token refreshed.
OTP‑POS‑05User resending OTP after expiry, SMS channel1. Tap Send OTP, receive code, wait 130 s (expired). 2. Tap Resend OTP. 3. Receive new code 111222. 4. Enter code, tap Verify.New code accepted, login succeeds.
OTP‑POS‑06User enters OTP with leading zeros (e.g., 001234)1. Send OTP, receive code 001234. 2. Enter exactly as shown, tap Verify.System treats leading zeros as significant, login succeeds.
OTP‑POS‑07User enters OTP via autocomplete from native OS suggestion bar1. Send OTP, receive SMS. 2. OS shows suggestion bar with code. 3. Tap suggestion to fill field. 4. Tap Verify.Login succeeds, same as manual entry.
OTP‑POS‑08User enters OTP after copying from clipboard (long‑press paste)1. Send OTP, receive SMS. 2. Long‑press SMS, copy code. 3. Long‑press OTP field, paste. 4. Tap Verify.Login succeeds.
OTP‑POS‑09User enters OTP with spaces auto‑stripped by system (e.g., “12 34 56”)1. Send OTP, receive code 123456. 2. Enter “12 34 56” (spaces). 3. Tap Verify.System ignores spaces, treats as 123456, login succeeds.
OTP‑POS‑10User completes OTP flow under low‑network condition (simulated 3G)1. Enable network throttling to 3G. 2. Send OTP, wait for delayed SMS. 3. Enter code, tap Verify.Login succeeds after slight delay, no timeout error.

These cases cover happy‑path scenarios across channels, input methods, and environmental factors.

Negative Test Cases for OTP Verification

Negative cases ensure the system rejects invalid input and enforces security controls.

IDPreconditionsStepsExpected Result
OTP‑NEG‑01User on login screen, OTP sent1. Enter incorrect 6‑digit code (e.g., 000000). 2. Tap Verify.System shows error “Invalid OTP”, remains on login screen, allows retry.
OTP‑NEG‑02User on login screen, OTP sent1. Leave OTP field blank. 2. Tap Verify.System shows field‑level validation error “OTP is required”.
OTP‑NEG‑03User on login screen, OTP sent1. Enter more than six digits (e.g., 1234567). 2. Tap Verify.System rejects input, shows “OTP must be 6 digits”.
OTP‑NEG‑04User on login screen, OTP sent1. Enter non‑numeric characters (e.g., abcdef). 2. Tap Verify.System shows “OTP must contain only numbers”.
OTP‑NEG‑05User on login screen, OTP sent1. Enter correct code after expiry (wait 130 s). 2. Tap Verify.System shows “OTP has expired”, forces resend.
OTP‑NEG‑06User on login screen, OTP sent1. Enter correct code, tap Verify (first success). 2. Immediately re‑enter same code, tap Verify again.System shows “OTP already used”, denies second verification.
OTP‑NEG‑07User on login screen, OTP sending rate‑limit in place1. Tap Send OTP five times within 10 s. 2. On fifth attempt, observe response.System blocks further sends, shows “Too many requests, try later”.
OTP‑NEG‑08User on login screen, OTP via SMS, SIM‑swap scenario simulated1. Send OTP to original number. 2. Change backend phone number to attacker‑controlled. 3. Attempt to use OTP sent to old number.System rejects OTP because phone number mismatch, logs security event.
OTP‑NEG‑09User on login screen, OTP field accessible via screen reader1. Enable TalkBack, focus OTP field. 2. Enter incorrect code via accessibility service. 3. Tap Verify.System reads error message aloud, does not proceed.
OTP‑NEG‑10User on login screen, OTP request tampered (MITM)1. Intercept OTP request via proxy, modify code_length parameter to 4. 2. Receive 4‑digit code. 3. Enter 4‑digit code, tap Verify.Backend rejects due to length mismatch, returns error.

These cases test validation, expiry, replay protection, rate limiting, and integrity of the OTP binding to the user identifier.

Edge and Boundary Cases for OTP Verification

Edge cases live at the limits of specifications and often surface only under stress or unusual user behavior.

IDPreconditionsStepsExpected Result
OTP‑EDG‑01System allows OTP length configurable (4‑8 digits)1. Configure backend for 4‑digit OTP. 2. Send OTP, receive 1234. 3. Enter 1234, tap Verify.Login succeeds with 4‑digit code.
OTP‑EDG‑02Same as above, but user enters 5‑digit code1. Enter 12345, tap Verify.System shows “OTP must be 4 digits”.
OTP‑EDG‑03OTP expiry configurable (30‑300 s)1. Set expiry to 30 s. 2. Send OTP, wait 31 s. 3. Enter code, tap Verify.System shows “OTP expired”.
OTP‑EDG‑04Maximum resend attempts limited (e.g., 3)1. Tap Send OTP three times quickly. 4. Tap Send OTP a fourth time.System blocks fourth send, shows “Resend limit reached”.
OTP‑EDG‑05OTP contains repeating digits (111111)1. Send OTP, receive 111111. 2. Enter 111111, tap Verify.Login succeeds; no special handling needed.
OTP‑EDG‑06OTP contains sequential digits (123456)1. Send OTP, receive 123456. 2. Enter 123456, tap Verify.Login succeeds.
OTP‑EDG‑07User pastes OTP with trailing newline from clipboard1. Copy OTP from SMS (includes newline). 2. Paste into field, tap Verify.System trims whitespace, login succeeds.
OTP‑EDG‑08User enters OTP using voice‑to‑text (speech input)1. Activate dictation, speak “one two three four five six”. 2. System inserts “123456”. 3. Tap Verify.Login succeeds if transcription accurate; otherwise shows error.
OTP‑EDG‑09OTP delivery channel fails (SMS gateway down)1. Disable SMS gateway in test environment. 2. Tap Send OTP. 3. Observe fallback or error.System shows “Unable to send OTP, try email or try later”.
OTP‑EDG‑10Concurrent OTP requests for same user (different sessions)1. Open two browser tabs, both trigger Send OTP simultaneously. 2. Receive two different codes. 3. Enter code from tab A in tab B, tap Verify.System rejects because code not associated with that session/binding.

These cases probe configurability, input sanitization, fallback mechanisms, and race conditions.

Data Setup, Test Environment, and Prioritization

Test Data Management

Environment Checklist

ComponentRecommended SettingReason
Test device/emulatorAndroid 10+ or iOS 14+ with latest security patchesEnsures OTP APIs behave as in production
Mock OTP providerConfigurable latency, success/failure togglesAllows injection of delayed or failed deliveries
LoggingCapture request/response payloads, OTP generation eventsFacilitates root cause analysis
SecurityDisable rate‑limit bypass in test mode only; re‑enable for CIPrevents accidental abuse while testing limits
AccessibilityTalkBack/VoiceOver enabledValidates error messages are announced

Prioritization Framework

Apply a simple risk‑based matrix:

Impact \ LikelihoodLowMediumHigh
Critical (security, compliance)P2P1P0
Major (core functionality loss)P3P2P1
Minor (UI glitch, cosmetic)P4P3P2
Trivial (spelling, rare edge)P5P4P3

Assign each test case a priority based on where it falls. For example:

Prioritization guides execution order in manual runs and helps decide which cases to automate first.

Manual Execution vs Automated Scripts

Manual Testing Strengths

Automation Strengths

Sample Automation Snippets

#### Appium (Java) – Positive SMS OTP


@Test
public void testValidSmtpOtpLogin() {
    // 1. Trigger OTP send
    driver.findElement(By.id("btn_send_otp")).click();
    // 2. Retrieve OTP from mock SMS gateway (REST call)
    String otp = HttpHelper.getOtpFromMockGateway(testUser.getPhone());
    // 3. Enter OTP
    WebElement otpField = driver.findElement(By.id("otp_input"));
    otpField.sendKeys(otp);
    // 4. Verify
    driver.findElement(By.id("btn_verify")).click();
    // 5. Assert landing page
    Assert.assertTrue(driver.findElement(By.id("home_screen")).isDisplayed());
}

#### Playwright (TypeScript – Negative expiry


test('expired OTP is rejected', async ({ page }) => {
  await page.goto('/login');
  await page.click('text=Send OTP');
  // fast‑forward clock 150 s (assuming test helper)
  await page.evaluate(() => { /* mock OTP service to return expired timestamp */ });
  const otp = await getOtpFromMock(page);
  await page.fill('#otp_input', otp);
  await page.click('text=Verify');
  await expect(page.locator('.error')).toHaveText('OTP has expired');
});

#### Bash CLI – Trigger SUSATest Exploration


# Install the agent
pip install susatest-agent
# Run a 5‑minute exploratory session on an Android APK
susatest explore --app ./myapp.apk \
                 --personas curious impatient elderly \
                 --max-duration 5m \
                 --output ./susatest-report.json

The agent will automatically attempt OTP flows, vary input timing, and log any crashes, ANRs, or validation failures it discovers.

Leveraging Autonomous Exploration with SUSATest

While hand‑crafted test cases provide depth, autonomous exploration adds breadth by exercising the app in ways a tester may not anticipate.

How SUSATest Works

  1. Ingestion – You supply an APK (Android) or a web URL.
  2. Personas – The agent simulates distinct behavior profiles (e.g., impatient users tap rapidly, elderly users linger, adversarial users fuzz inputs).
  3. Exploration – It navigates screens, fills fields, handles dialogs, and attempts real user flows such as login, signup, or checkout.
  4. Observation – It logs crashes, ANRs, dead buttons, WCAG violations, security hints, and UX friction.
  5. Script Generation – From successful paths it auto‑creates regression scripts in Appium (Android) and Playwright (Web).

Integrating SUSATest with OTP Verification

#### Example: Discovering a Race Condition

During an exploratory run, the adversarial persona triggered two OTP requests within 200 ms, received two distinct codes, and attempted to verify the first code in the second session. The agent logged a failure: “OTP verification succeeded despite session mismatch”. This insight led to adding a new test case (OTP‑EDG‑10) to the matrix.

Benefits

Limitations

Test Case Traceability and Requirements Mapping

Linking each test case to a requirement ensures that verification effort aligns with product specifications and supports audit trails.

Requirements Example

REQ‑IDDescription
REQ‑OTP‑01System shall send a 6‑digit numeric OTP numeric range 1000000.
REQ‑OTP‑02OTP must be valid for exactly 120 seconds after generation.
REQ‑03OTP shall be bound to the user request REQ‑OTP‑04System shall send a 6‑digit numeric OTP to the user's registered phone number or email upon request.
REQ‑OTP‑02OTP shall expire after a configurable time window (default 120 s).
REQ‑OTP‑03OTP shall be usable only once used successfully.
REQ‑OTP‑04System shall limit OTP generation requests to N per minute per user to prevent abuse.
REQ‑OTP‑05System shall reject OTP attempts with incorrect format, length, or non‑numeric characters.
REQ‑OTP‑06System shall provide clear, accessible error messages for OTP failures.
REQ‑OTP‑07System shall support OTP delivery via SMS, email, push, and voice channels.
REQ‑OTP‑08System shall allow users to resend OTP up to M times before temporary lockout.
REQ‑OTP‑09System shall log OTP request, success, and failure events for security auditing.
REQ‑OTP‑10System shall ensure OTP is tied to the exact user identifier (phone/email) that requested it.

Traceability Table (excerpt)

Test Case IDCovered REQ‑IDsNotes
OTP‑POS‑01REQ‑OTP‑01, REQ‑OTP‑02, REQ‑OTP‑03Valid code within expiry, single use
OTP‑NEG‑01REQ‑OTP‑05Incorrect numeric code
OTP‑NEG‑05REQ‑OTP‑02Expired code
OTP‑NEG‑06REQ‑OTP‑03Replay attempt
OTP‑NEG‑07REQ‑OTP‑04Rate‑limit enforcement
OTP‑EDG‑09REQ‑OTP‑07Fallback when SMS fails
OTP‑EDG‑10REQ‑OTP‑10Session binding verification
OTP‑POS‑07REQ‑OTP‑01, REQ‑OTP‑06Autocomplete accessibility

Maintain this table in a version‑controlled spreadsheet or a test management tool (e.g., Zephyr, TestRail). When a requirement changes, you can instantly see which test cases need review.

Practical Checklist for OTP Verification Testing

Use this checklist before signing off a release:

If any item is unchecked, investigate and update the test suite before promoting the build.

Takeaways and Next Steps

Writing effective test cases for OTP verification is not merely about checking “correct code → success”. It requires a deep understanding of the entire verification lifecycle, disciplined case anatomy, and a blend of positive, negative, and edge scenarios that reflect real‑world usage and attack vectors.

By combining carefully crafted test cases with smart, persona‑driven exploration, you achieve both depth and breadth in OTP verification coverage, reducing the risk of production‑facing failures and strengthening user trust in your authentication mechanisms.

---

*End of guide.*

Test Your App Autonomously

Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.

Try SUSA Free