How to Write Test Cases for Forgot Password (With Examples)

How to Write Test Cases for Forgot Password (With Examples)

March 13, 2026 · 17 min read · How-To Guides

How to Write Test Cases for Forgot Password (With Examples)

Forgot‑password functionality is a critical gate‑keeper for account recovery, yet it is often under‑tested because the flow appears simple. In reality, a robust test suite must verify that legitimate users can reset their credentials quickly, that malicious actors cannot abuse the mechanism, and that edge‑case inputs do not cause crashes or leak information. This guide walks you through the complete process of designing, prioritizing, and executing test cases for a forgot‑password feature, providing a concrete matrix of 20+ examples, a short checklist, and practical tips for combining manual exploratory testing with automated regression scripts. By the end you will have a ready‑to‑use test‑case template that you can adapt to any web or mobile application.

1. Understanding the Forgot Password Flow

Before writing test cases you need a clear mental model of the typical reset‑password sequence. Most implementations follow these logical steps:

  1. User entry – The user supplies an identifier (usually email or username) on a “Forgot password?” page.
  2. Validation – The system checks that the identifier matches an existing account and that the account is in a recoverable state (not locked, not marked for deletion).
  3. Token generation – A cryptographically‑random, single‑use token is created and stored (often hashed) together with an expiration timestamp.
  4. Notification – The token (or a URL containing it) is sent to the user via email, SMS, or an in‑app message.
  5. User interaction – The user clicks the link, arrives at a reset‑password page, and enters a new password that satisfies policy rules.
  6. Verification – The system validates the token, ensures it has not been used or expired, updates the password hash, invalidates any existing sessions, and confirms success.
  7. Post‑reset actions – The user is redirected to a login page or a “password changed” screen, and a security notification is sent.

Each step introduces distinct test concerns: input validation, business logic, cryptographic security, usability, and auditability. Keeping this flow in mind helps you avoid gaps when you enumerate test cases.

1.1 Typical Variations

Understanding which variations apply to your product shapes the set of test cases you will need.

1.2 Security Goals

A forgot‑password flow must satisfy three core security properties:

Your test cases should explicitly target each property.

2. Anatomy of a Test Case

A well‑structured test case makes it easy to review, automate, and trace back to requirements. The following fields are essential:

FieldDescription
IDUnique identifier (e.g., FP‑001) that enables traceability and easy reference in defect reports.
TitleConcise, readable summary of what is being verified (e.g., “Valid email triggers reset link”).
PreconditionsState that must be true before execution (e.g., “User exists with email alice@example.com, account is active, no pending reset”).
StepsNumbered actions the tester performs, including any data entry, navigation, or API calls.
Expected ResultObservable outcome that determines pass/fail (e.g., “System sends an email containing a single‑use reset link within 30 seconds”).
Actual ResultFilled in after execution; used to log defects.
PriorityTypically P0 (critical), P1 (high), P2 (medium), P3 (low) based on risk and impact.
TraceabilityLink to the originating requirement, user story, or design spec (e.g., “REQ‑AUTH‑07”).
NotesOptional field for environment specifics, data cleanup, or observations.

When you write a test case, fill in every field before execution. Leaving a field blank invites ambiguity and makes later traceability harder.

2.1 Writing Clear Steps

Steps should be imperative, atomic, and free of assumptions. For example:

  1. Navigate to https://app.example.com/forgot.
  2. Enter alice@example.com into the Email field.
  3. Click the Submit button.
  4. Wait for the success toast message to appear.

Avoid bundling multiple actions into a single step; otherwise, debugging a failure becomes guesswork.

2.2 Choosing Expected Results

Expected results must be observable and measurable. Instead of “system behaves correctly,” specify:

Concrete expectations enable both manual verification and automated assertions.

3. Positive Test Cases

Positive tests confirm that the happy path works for legitimate users. Below are categories of positive scenarios, each with representative test cases.

3.1 Valid Identifier Submission

IDTitlePreconditionsStepsExpected Result
FP‑001Valid email triggers reset linkUser exists, email alice@example.com, account active1. Open forgot‑password page.
2. Enter alice@example.com.
3. Click Submit.
System returns success message; email with reset link is delivered within 30 s.
FP‑002Username (if supported) triggers reset linkUsername bob123 maps to existing accountSame as FP‑001 using username field.Same as FP‑001.
FP‑003Phone number (if supported) triggers reset linkPhone +1‑555‑123‑4567 registered, SMS enabledEnter phone number, click Submit.SMS with reset link received within 30 s.

3.2 Token Validity and Expiration

IDTitlePreconditionsStepsExpected Result
FP‑004Token works within validity windowReset link sent (FP‑001) not yet clicked1. Open email, copy link.
2. Paste link in browser.
3. Enter new password NewPass!23.
4. Click Reset.
Password updated; user redirected to login page; success toast shown.
FP‑005Token rejected after expirationReset link sent, system clock advanced > expiry (e.g., 24 h)Same as FP‑004 but after waiting for expiry.Error message: “Link has expired. Please request a new reset link.”
FP‑006Token single‑use enforcementReset link sent, not yet used1. Use link to reset password successfully (FP‑004).
2. Attempt to use same link again.
Second attempt yields error: “Invalid or already used token.”

3.3 Password Policy Compliance

IDTitlePreconditionsStepsExpected Result
FP‑007Accepts password meeting policyToken valid, password policy: ≥8 chars, 1 upper, 1 digit, 1 symbolEnter Secure9! on reset page, submit.Password changed; success message.
FP‑008Rejects password missing required character classSame as FP‑007Enter secure (no upper, digit, symbol).Inline validation error: “Password must contain at least one uppercase letter, one digit, and one symbol.”
FP‑009Rejects password too shortSame as FP‑007Enter Ab1! (4 chars).Error: “Password must be at least 8 characters long.”
FP‑010Prevents reuse of recent passwordsUser’s last 3 passwords stored: Old1!, Old2@, Old3#Attempt to set new password to Old1!.Error: “You cannot reuse your last three passwords.”

3.4 User Experience Feedback

IDTitlePreconditionsStepsExpected Result
FP‑011Success toast appears after resetToken validComplete FP‑004Toast “Password changed successfully” displayed for ≥ 3 seconds.
FP‑012Email notification sent after resetToken validComplete FP‑004User receives email “Your password has been changed” within 1 minute.
FP‑013Session invalidation after resetUser has active session on another devicePerform FP‑004, then try to access a protected page on other device.Redirect to login page; session token invalid.

These positive cases establish that the core flow works under normal conditions and that the system gives appropriate feedback.

4. Negative Test Cases

Negative tests verify that the system correctly handles invalid or malicious input. They are essential for preventing information leakage, abuse, and denial‑of‑service.

4.1 Invalid or Non‑existent Identifiers

IDTitlePreconditionsStepsExpected Result
FP‑014Non‑existent email returns generic messageNo account with nonexist@example.comEnter email, click Submit.Message: “If the address exists, you will receive a reset link.” (no hint whether address exists).
FP‑015Email with wrong domain returns same genericSame as FP‑014Enter alice@wrongdomain.com.Same generic message.
FP‑016Username with special chars returns genericUsername bob!$ not registeredEnter username, click Submit.Same generic message.
FP‑017Blank identifier fieldForm loadedLeave email empty, click Submit.Inline validation: “Email is required.”
FP‑018Whitespace‑only identifierSame as FP‑017Enter spaces, click Submit.Same validation error.

4.2 Rate Limiting and Abuse Protection

IDTitlePreconditionsStepsExpected Result
FP‑019Rate limit per‑minute throttling on submitNo prior attempts in current minuteRapidly click Submit 10 times with same email.After 5 attempts, system shows “Too many requests; try again later.”
FP‑020 per‑hour lockout after failuresNo lockout in placeSubmit invalid email 15 times within hour.After 10 failures, system displays “Account temporarily locked; try again in 60 min.”
FP‑021 CAPTCHA after repeated failuresSame as FP‑020After 5 failed attempts, system presents CAPTCHA.User must solve CAPTCHA before next submit attempt.

4.3 Token Tampering and Replay

IDTitlePreconditionsStepsExpected Result
FP‑022 Modified token rejectedValid token obtained (FP‑004)1. Copy reset link.
2. Change one character in token query param.
3. Navigate to altered link.
Error: “Invalid token.”
FP‑023 Token replay after useToken used successfully (FP‑004)Re‑use same link after password change.Error: “Token already used.”
FP‑024 Token with future timestamp rejectedSystem allows setting custom clock (test env)Generate token with expiry + 30 days, use immediately.Error: “Invalid token.”
FP‑025 Token replay across accountsTwo accounts A and B, token for AAttempt to use A’s token to reset B’s password.Error: “Token does not belong to this account.”

4.4 Information Leakage Checks

IDTitlePreconditionsStepsExpected Result
FP‑026 No account existence hint in responseSame as FP‑014Submit non‑existent email.HTTP status 200, response body identical to that for existing email (no “user not found”).
FP‑027 No partial email in logs or UISame as FP‑014Submit any email, inspect network logs and UI toast.Logs contain only hashed identifier; UI never shows the entered email in error messages.
FP‑028 No token in URL referrer headerToken validClick reset link from email, navigate to external site.Referer header does not contain the full reset URL (token stripped) or site uses rel=noreferrer.

These negative cases ensure that the system does not aid attackers by revealing whether an address is registered, by allowing token reuse, or by failing to enforce rate limits.

5. Boundary and Edge‑Case Tests

Boundary conditions often expose bugs that slip through happy‑path testing. Test the limits of input length, character sets, and concurrency.

5.1 Input Length Limits

IDTitlePreconditionsStepsExpected Result
FP‑029 Maximum email length acceptedSystem defines max 254 chars (RFC 5321)Generate email a × 240 + @example.com (254).Enter email, click Submit.Success; reset link sent.
FP‑030 Email longer than limit rejectedSame as FP‑029Email a × 250 + @example.com (259).Enter email, click Submit.Validation error: “Email address is too long.”
FP‑031 Minimum email length acceptedSystem allows 3‑char local partEmail ab@cd.com (6 chars).Enter email, click Submit.Success (if domain valid).
FP‑032 Email shorter than limit rejectedSame as FP‑031Email a@b.c (5 chars) – invalid domain format.Enter email, click Submit.Validation error: “Please enter a valid email address.”

5.2 Character Set and Unicode

IDTitlePreconditionsStepsExpected Result
FP‑033 Email with plus‑sign (gmail style)Account exists with alice+test@example.comEnter alice+test@example.com, click Submit.Success; reset link delivered to the same inbox.
FP‑034 Email with sub‑addressing (hyphen)Account bob‑work@example.com existsEnter bob‑work@example.com.Success.
FP‑035 Email with Unicode charactersAccount 用户@例子.cn exists (IDN)Enter 用户@例子.cn.Success; system normalizes to punycode internally and sends link.
FP‑036 Email with leading/trailing spacesSame as FP‑001Enter “ alice@example.com ” (spaces).System trims whitespace; treats as valid email.
FP‑037 Email with multiple consecutive dotsSame as FP‑001Enter alice..smith@example.com.Validation error: “Email address contains invalid characters.”

5.3 Concurrent Requests and Race Conditions

IDTitlePreconditionsStepsExpected Result
FP‑038 Parallel reset requests for same accountUser has active session, no pending reset1. Open two browser tabs.
2. In each, submit FP‑001 simultaneously.
3. Observe responses.
Only one reset link is generated and sent; second request returns “A reset link has already been sent; please check your email.”
FP‑039 Token generation under high loadSystem under simulated load (e.g., 100 req/s)Use a load‑generator to send reset requests for distinct accounts.All requests receive success responses; no HTTP 500 errors; each email receives a unique link.
FP‑040 Password change while reset link pendingUser requests reset, then attempts to change password via settings before using link1. Trigger FP‑001.
2. Without clicking email, navigate to Settings → Change Password and submit new password.
Settings change succeeds; the previously sent reset link becomes invalid (error if used).

These boundary cases test validation logic, Unicode handling, and concurrency safeguards that are often missed in scripted tests.

6. Security‑Focused Test Cases

Beyond functional correctness, the forgot‑password flow must resist specific attack vectors. The following cases target common weaknesses.

6.1 Token Entropy and Predictability

IDTitlePreconditionsStepsExpected Result
FP‑041 Token length ≥ 32 bytesSystem generates token via cryptographically‑secure RNGRequest reset for any account, capture token from email.Token string (base64‑url) length ≥ 43 chars (≈32 bytes).
FP‑042 Token contains sufficient entropySame as FP‑041Collect 1000 tokens, compute Shannon entropy.Entropy ≈ log₂(N) where N is token space; should be > 60 bits.
FP‑043 Token not derivable from user dataSame as FP‑041Attempt to predict token using username, email, timestamp.No statistical correlation; prediction success rate ≈ random guess.

6.2 Replay and Man‑in‑the‑Middle Mitigations

IDTitlePreconditionsStepsExpected Result
FP‑044 HTTPS enforced for reset linkToken validCapture reset link; verify URL scheme is https://.Link uses HTTPS; if HTTP, test fails.
FP‑045 HSTS header on reset‑page domainSame as FP‑044Perform a curl -I request to reset‑page domain.Response includes Strict-Transport-Security header with max‑age≥31536000.
FP‑046 Token bound to IP address (optional)System implements IP‑bindingRequest reset from IP A, obtain link.
Attempt to use link from IP B.
Error: “Token invalid for this IP address.” (if feature enabled).

6.3 Logging and Alerting

IDTitlePreconditionsStepsExpected Result
FP‑047 Failed reset attempts loggedNo prior attemptsSubmit invalid email 5 times.Security log contains entries: FAILED_RESET email=… reason=INVALID_FORMAT.
FP‑048 Successful reset triggers audit entryToken validComplete FP‑004.Audit log: PASSWORD_RESET userId=123 outcome=SUCCESS timestamp=….
FP‑049 Rate‑limit exceeded triggers alertSame as FP‑019Exceed threshold (e.g., 20 requests/min).Monitoring system receives alert: RESET_RATE_LIMIT_EXCEEDED.

These security tests give you confidence that the mechanism does not become a weak point in your overall authentication strategy.

7. Prioritization and Traceability

A large test suite needs a rational ordering so that the most critical defects are found early, especially when time is limited.

7.1 Risk‑Based Scoring Model

Assign each test case a Risk Score = (Impact × Likelihood). Impact reflects the severity of a failure (e.g., account takeover = 5, UI glitch = 1). Likelihood estimates how often the condition occurs in production (e.g., malformed input = 3, token reuse = 2). Prioritize tests with the highest scores.

Score RangePriority LabelTypical Content
20‑25P0 (Critical)Token reuse, account enumeration, HTTPS missing
15‑19P1 (High)Rate limiting, password policy enforcement
10‑14P2 (Medium)Edge‑case input lengths, Unicode handling
5‑9P3 (Low)Cosmetic messages, non‑essential logging

Apply this model to the matrix above; you will see that FP‑022, FP‑023, FP‑044, and FP‑047 typically fall into P0.

7.2 Requirements Traceability Matrix (RTM)

Link each test case to the requirement(s) it validates. Below is a simplified RTM showing a few requirements from a typical auth spec.

Requirement IDDescriptionCovered Test Cases
REQ‑AUTH‑07System shall allow password reset via emailFP‑001, FP‑002, FP‑003, FP‑004, FP‑005, FP‑006
REQ‑AUTH‑08Reset token must be single‑use and time‑boundFP‑005, FP‑006, FP‑022, FP‑023
REQ‑AUTH‑09No user‑enumeration via reset endpointFP‑014, FP‑015, FP‑016, FP‑026
REQ‑AUTH‑10Rate‑limit reset requests to prevent abuseFP‑019, FP‑020, FP‑021
REQ‑AUTH‑11Password must meet policy on resetFP‑007, FP‑008, FP‑009, FP‑010
REQ‑AUTH‑12Successful reset must invalidate existing sessionsFP‑013
REQ‑AUTH‑13All reset activity must be auditedFP‑047, FP‑048, FP‑049

Maintaining this matrix in a spreadsheet or test‑management tool lets you quickly see which requirements lack coverage and guides test‑case creation when specs evolve.

8. Manual vs. Automated Execution

Both approaches have merit. Manual exploratory testing uncovers usability quirks and unexpected states, while automated regression guards against re‑introducing known defects.

8.1 Manual Exploratory Testing with SUSA

SUSA (the autonomous QA platform) can be pointed at your web or mobile app and will exercise the forgot‑password flow using a variety of user personas—curious, impatient, novice, adversarial, elderly, accessibility‑focused, power user, etc. Each persona follows its own behavior profile, which may reveal issues that scripted tests miss.

Typical workflow:


# Install the agent
pip install susatest-agent

# Point SUSA at a staging URL (web) or provide an APK (Android)
susatest run --url https://staging.example.com \
             --personas curious impatient adversarial \
             --timeout 15m \
             --output report.html

During a run, SUSA will:

  1. Locate the “Forgot password?” link (often via text‑match or accessibility label).
  2. Attempt to submit various identifiers (valid, invalid, long, special‑char).
  3. Follow any email links it discovers (if a test mailbox is configured).
  4. Try to reset passwords with weak, strong, and policy‑violating new passwords.
  5. Observe UI messages, network responses, and any crashes or ANRs.

Because SUSA learns from each session, subsequent runs become smarter—avoiding previously dead ends and focusing on new avenues. Use its output as a starting point for manual investigation: flag any unexpected behavior, then write a focused test case (or automate it) to cover the gap.

8.2 Scripted Automation (Appium + Playwright)

After you have a solid set of test cases, encode the repetitive ones in code. Below are minimal examples for Android (Appium) and web (Playwright). Adjust selectors and data to match your application.

#### Appium (Java) – Valid Email Reset


@Test
public void testValidEmailTriggersReset() {
    driver.get("https://app.example.com/forgot");
    WebElement email = driver.findElement(By.id("forgotEmail"));
    email.sendKeys("alice@example.com");
    driver.findElement(By.id("submitBtn")).click();

    // Wait for toast
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    WebElement toast = wait.until(ExpectedConditions.visibilityOfElementLocated(By.className("toast-success")));
    assertTrue(toast.getText().contains("Reset link sent"));

    // In a real test you would pull the link from a mailbox API here
}

#### Playwright (TypeScript) – Token Expiration


test('reset link expires after 24h', async ({ page }) => {
  await page.goto('https://app.example.com/forgot');
  await page.fill('#forgotEmail', 'bob@example.com');
  await page.click('#submitBtn');

  // Assume we have a test mailbox that returns the latest link
  const resetLink = await getLatestResetLink('bob@example.com');
  await page.goto(resetLink);

  // Simulate time travel: set system clock ahead via mock API (test‑only)
  await page.route('**/api/set-clock', route => route.fulfill({ json: { offsetHours: 25 } }));
  await page.waitForTimeout(500); // let mock apply

  await page.fill('#newPassword', 'NewPass!23');
  await page.click('#resetBtn');

  const error = await page.locator('.error-message').innerText();
  expect(error).toContain('Link has expired');
});

These snippets illustrate how to automate the most common positive and negative paths. Store test data (emails, passwords) in a secure vault or generate them on‑the‑fly to avoid hard‑coding secrets.

8.3 CI Integration

Add the automated tests to your pipeline so they run on every pull request. A typical GitHub Actions snippet:


name: Forgot Password Regression
on: [pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up Node
        uses: actions/setup-node@v3
        with:
          node-version: '20'
      - name: Install dependencies
        run: npm ci
      - name: Run Playwright tests
        run: npx playwright test --project=chromium
      - name: Upload report
        if: always()
        uses: actions/upload-artifact@v3
        with:
          name: playwright-report
          path: playwright-report/

For mobile, replace the Playwright step with an Appium execution using a Docker image that contains the Android emulator and the Appium server.

Combining SUSA’s exploratory runs (perhaps nightly) with the CI‑gated automated suite gives you both breadth and depth.

9. Worked Test Matrix (20+ Cases)

Below is a consolidated table that you can copy into your test‑management tool. It includes ID, short title, preconditions, steps, and expected result. Feel free to extend it with your own project‑specific variations.

IDTitlePreconditionsStepsExpected Result
FP‑001Valid email triggers reset linkUser alice@example.com exists, active1. Open forgot‑password page.
2. Enter alice@example.com.
3. Click Submit.
Success toast; email with reset link delivered within 30 s.
FP‑002Username triggers reset link (if supported)Username bob123 maps to existing accountSame as FP‑001 using username field.Same as FP‑001.
FP‑003Phone number triggers reset link (if supported)Phone +1‑555‑123‑4567 registered, SMS enabledEnter phone number, click Submit.SMS with reset link received within 30 s.
FP‑004Token works within validity windowReset link sent (FP‑001) not yet clicked1. Open email, copy link.
2. Paste link in browser.
3. Enter new password NewPass!23.
4. Click Reset.
Password updated; redirected to login; success toast shown.
FP‑005Token rejected after expirationReset link sent, system clock advanced > expiry (e.g., 24 h)Same as FP‑004 but after waiting for expiry.

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