Great work!

XP to next level

BugEater

Testing Case Sensitivity Effectively

Testing case sensitivity is not about finding every possible combination of uppercase and lowercase. It is about finding the boundaries of the case policy and verifying that every code path enforces that policy consistently.

Step 1: Identify the Fields

Not all fields need case-sensitivity testing. Focus on fields that:

  • Are compared for equality (authentication, lookup, uniqueness checks)
  • Have a security function (tokens, codes, keys)
  • Are displayed to users after storage (display consistency)
  • Feed into another system's comparison (cross-service usernames, IDs)

Fields that are purely stored and displayed without comparison (a bio, a product description, a note) have lower case-sensitivity risk — the main question is only whether storage preserves the original case faithfully.

Step 2: Define the Expected Policy

For each field, determine the intended policy:

  • Case-sensitive: Admin and admin are different values
  • Case-insensitive, normalize on input: all values are stored in a canonical case (lowercase or uppercase); comparisons use the stored canonical form
  • Case-insensitive, normalize on comparison: values are stored as-submitted; comparisons always normalize both sides

Document this policy explicitly before testing. Without it, you cannot determine whether a behavior is a bug or a feature.

Step 3: Build the Test Matrix

For a case-insensitive username field that normalizes to lowercase on input:

Test Input Expected stored Expected login Notes
All lowercase admin admin ✓ with admin Baseline
All uppercase ADMIN admin ✓ with ADMIN, admin Normalized on storage
Mixed case Admin admin ✓ with Admin, admin Normalized on storage
Mixed case aDmIn admin ✓ with aDmIn, admin Normalized on storage
With non-ASCII Ädmin depends need spec Is Ä normalized to ä?

For a case-sensitive password field:

Test Input Expected stored Expected auth Notes
Exact case P@ssw0rd hashed ✓ with P@ssw0rd Baseline
All lowercase p@ssw0rd Different password
All uppercase P@SSW0RD Different password
One char changed P@ssW0rd Case difference matters

Step 4: Test Every Code Path

For each field in the matrix, test every code path that accepts the same value:

  • Registration / creation endpoint
  • Login / authentication endpoint
  • Password reset / account recovery
  • Profile lookup / search
  • Admin panel search and management
  • API endpoints (may have separate implementations)
  • Email-triggered flows (confirmation, notification)

The goal: verify that all paths apply the same case policy. A single inconsistent path is a bug.

Step 5: Test Cross-System Boundaries

If the application integrates with external systems, also test:

  • SSO / OAuth: does the external provider normalize case? Does your application handle mismatches?
  • Exported data (CSVs, reports): is case preserved or normalized?
  • Imported data: if you import a user with ADMIN, what case is stored?
  • Webhooks and event payloads: does the receiving system compare case correctly?

Common Findings

The most common case-sensitivity bugs found in real applications:

  1. Inconsistent normalization: Registration lowercases, login does not — users who registered with uppercase letters cannot log in
  2. Case-sensitive UNIQUE constraint: Allows both admin and Admin to be registered — different records exist for visually identical usernames
  3. Token case-insensitivity: A password reset token matches even with wrong case — reduced security
  4. Search doesn't find all records: Case-sensitive search in a case-insensitive application — admin cannot find a user by typing their name in a different case
  5. Display inconsistency: Username stored as admin but displayed as the originally submitted Admin because the display path reads from a different source than the storage path

Quiz

When writing test cases for a username field that should be case-insensitive, which input set provides the most complete coverage?

A requirements document says "email addresses must be unique". A tester registers with user@example.com then tries User@Example.COM. What should the system do?

A tester wants to verify that a case-insensitive search for "Berlin" returns the same results as "BERLIN" and "berlin". What is the most rigorous verification approach?

Which SQL query correctly checks for existing case-insensitive duplicate usernames before inserting?