Error Guessing: How Experienced Testers Use Intuition Systematically

Error Guessing: How Experienced Testers Use Intuition Systematically

Error guessing is the test design technique that most testers use without realizing it's a technique. You look at a form and immediately think: "What happens if I put a script tag in this field?" You see a pagination component and wonder: "What happens on page zero?" You review an API endpoint and instinctively try a negative number where only positives are documented.

That's not randomness. That's accumulated experience being applied. Error guessing as a formal technique is about making that experience explicit, transferable, and comprehensive rather than leaving it as a black box labeled "gut feeling."

What Error Guessing Is

Glenford Myers defined error guessing in The Art of Software Testing as a technique where the tester uses intuition and experience to guess what errors are likely. It's explicitly experience-driven and complements formal techniques like equivalence partitioning and boundary value analysis — it covers the cases the formal techniques miss.

The formal definition: the tester enumerates a list of possible errors or error-prone situations and then designs tests to expose those errors. The key word is "enumerates." Error guessing done well produces a documented list, not a stream of consciousness.

The difference between a junior tester doing error guessing and a senior tester doing error guessing:

  • Junior: tries a few things that seem likely to break, based on limited experience
  • Senior: works through a mental catalog of known error patterns by domain, input type, system type, and technology stack

The senior's advantage isn't magic. It's pattern recognition built from years of seeing where bugs actually live.

The Error Taxonomy: Where Bugs Actually Live

Experienced testers recognize recurring bug categories. Knowing these categories is the starting point for systematic error guessing.

Boundary and Edge Values (Beyond Formal BVA)

Formal boundary value analysis gives you min, min+1, max-1, max. Error guessing extends this:

  • Zero: Not just "minimum value" but specifically 0. Division by zero. Empty collections. Zero-length strings. Systems that handle "less than 1" poorly.
  • One: Single-element lists. Single-character strings. Systems that were tested with multiple items but not with exactly one.
  • Exact powers of 2: 128, 256, 512, 32768, 65536. Systems that use bit manipulation or fixed buffers often fail at these values.
  • Signed integer overflow: 2,147,483,647 (max 32-bit signed int) and 2,147,483,648. Common in systems mixing languages or using implicit type conversions.
  • The "off by one" family: Loop termination at < vs <=, array indices at length vs length-1, date ranges at "before midnight" vs "at midnight."

Input Type Abuse

  • Type mismatches: String where integer expected, float where integer expected (1.5 as a quantity), boolean as number (true = 1, false = 0).
  • Unicode edge cases: Null character (U+0000). Right-to-left text in left-to-right forms. Characters that normalize differently (é as precomposed vs combining character). Emojis in name fields (they're valid Unicode). The zero-width joiner.
  • SQL injection patterns: '; DROP TABLE users; -- is the cliché, but more realistic: O'Brien in a name field that breaks a naive SQL query.
  • HTML/script injection: <script>alert(1)</script> in any text field that might be rendered. Less about security testing, more about verifying output encoding.
  • Whitespace: Leading spaces. Trailing spaces. Tabs. Multiple consecutive spaces. Newlines in single-line fields. A string that is only whitespace.
  • Maximum length and beyond: Enter exactly max_length characters (valid). Enter max_length + 1 (boundary). Enter 10,000 characters (stress). Enter a 1MB string (extreme).

State and Timing

  • Do it twice: Submit a form twice rapidly. Click a button twice. What happens on the second identical request?
  • Concurrent actions: Two users modifying the same record simultaneously. The same user in two tabs.
  • Interrupt the flow: Navigate away mid-process. Close the browser. Kill the network connection. What state is the system in?
  • Do it out of order: Try to complete step 3 before step 1. Bookmark a deep link and navigate directly.
  • Do it after it's done: Confirm a completed transaction again. Delete something that's already deleted. Complete a flow that was cancelled.

System and Integration Stress

  • Empty everything: Empty database table. No results returned. Empty file. Empty list. Zero recipients.
  • Full everything: Maximum number of records. Disk full. Memory limit. Queue at capacity.
  • Unavailable dependencies: External service down. Database connection lost. Third-party API returning 503.
  • Slow dependencies: External service responding in 30 seconds instead of 300ms. Database query that normally takes 10ms now takes 10 seconds.
  • Time-based errors: Daylight saving time transitions. Leap year (especially February 29). End of month (especially January 31 → February). Year boundaries (December 31 → January 1). Unix timestamp at 2^31 − 1 (January 19, 2038).

Permission and Authorization Gaps

  • Horizontal privilege escalation: User A accessing User B's data by changing an ID in the URL.
  • Vertical privilege escalation: Regular user accessing admin functionality.
  • Stale permissions: A user whose role changed is still logged in. Does the old session reflect the new permissions?
  • Direct object reference: The UI doesn't show a delete button, but DELETE /api/item/123 still works.
  • Unauthenticated access: What happens when the Authorization header is absent? Expired? Forged?

Domain-Specific Error Patterns

Financial Systems

Rounding and precision:

0.1 + 0.2 = 0.30000000000000004  (floating point)

Any system doing money arithmetic in floating point is wrong. Tests:

  • Does $0.10 + $0.20 = $0.30 exactly, or does the system have a floating-point bug?
  • Does the system handle three decimal places? (Some currencies have 3 decimal places: KWD, BHD)
  • What happens with currency conversion at 4+ decimal precision?

Negative balances and overdrafts:

  • Transfer that would result in negative balance: blocked?
  • Refund that exceeds original charge: allowed?
  • Chargeback resulting in negative balance: handled?

Concurrency:

  • Two simultaneous withdrawals from an account with insufficient balance for both: does exactly one succeed, or do both?
  • This is the classic race condition in financial systems, and it fails surprisingly often.

E-commerce and Inventory

Quantity edge cases:

  • Add 0 items to cart
  • Add negative quantity (attempt to remove via quantity field)
  • Add more than available stock
  • Add maximum stock (last remaining item)
  • Add item, then item goes out of stock before checkout

Pricing:

  • Apply coupon code that reduces price below $0
  • Apply multiple coupons simultaneously
  • Price changes between "add to cart" and "checkout"
  • Tax calculation that results in a fraction of a cent

Cart and session:

  • Abandon cart and return 7 days later (still valid?)
  • Add to cart in one browser, complete purchase on mobile — what's in each cart?
  • Share cart URL (does it work? should it?)

Authentication Systems

Password validation:

  • Password exactly at minimum length
  • Password exactly at maximum length
  • Password that is all spaces
  • Password with only special characters
  • Unicode password: passwords with emoji, accented characters
  • The same password with different capitalization

Session management:

  • Log in, wait for session to expire, try to perform an action
  • Log in from two different browsers, log out from one — does the other session die?
  • Password reset: does old password stop working immediately?
  • Account locked: is the lock per-username, per-IP, or per-combination?

OAuth and SSO:

  • What happens when the OAuth provider is down?
  • What happens when the OAuth token expires mid-session?
  • CSRF: does the state parameter protect against cross-site request forgery?

APIs

HTTP method abuse:

  • DELETE /users/123 — does it work without authentication?
  • PUT where only POST is documented — does the undocumented method work?
  • GET /users/123 with a body — does the body cause an error?

Content type negotiation:

  • Content-Type: application/xml to a JSON API
  • Content-Type: text/plain with JSON body
  • Missing Content-Type header entirely

Large payloads:

  • Request body of 1MB, 10MB, 100MB — at what size does the server reject it?
  • Array with 10,000 elements
  • Nested objects 50 levels deep

Malformed inputs:

  • JSON with a trailing comma: {"key": "value",}
  • Duplicate keys in JSON: {"id": 1, "id": 2} — which value wins?
  • Integer field with a decimal: {"count": 1.5}
  • String field with null: {"name": null} vs missing key entirely

The Error Guess List: Making It Systematic

The way to turn error guessing from intuition into a technique: before testing, write down your guesses.

Format: for each feature or component, list the specific errors you're going to try to induce. Not vague categories — specific inputs and actions.

Example for a user profile photo upload:

Error guess list: Profile photo upload

Boundary/size:
[ ] Upload exactly 5MB file (at stated limit)
[ ] Upload 5MB + 1 byte
[ ] Upload 0-byte file
[ ] Upload 1-pixel × 1-pixel image
[ ] Upload 10,000 × 10,000 pixel image

File type abuse:
[ ] Upload .txt file renamed to .jpg
[ ] Upload .php file (code execution attempt)
[ ] Upload SVG with embedded JavaScript
[ ] Upload a valid JPEG with malicious EXIF data
[ ] Upload a file with no extension
[ ] Upload a ZIP file renamed as .jpg (polyglot file)

Format edge cases:
[ ] Upload progressive JPEG
[ ] Upload JPEG with CMYK color space (not RGB)
[ ] Upload animated GIF
[ ] Upload a valid PNG with no image data (1×1 transparent)

Process:
[ ] Upload while slow network (drop to 3G speed)
[ ] Navigate away during upload
[ ] Reload page during upload
[ ] Upload twice simultaneously (two tabs)
[ ] Delete account while upload is in progress

State:
[ ] Upload when account storage is full
[ ] Upload when user has no permission to change profile (restricted account)

This list takes 10-15 minutes to produce for a feature you know well. It ensures you don't skip the SVG XSS test because something else caught your attention.

Combining Error Guessing with Formal Techniques

Error guessing is a complement, not a replacement.

The layered approach:

  1. Specification-based techniques (equivalence partitioning, boundary value analysis) — systematic coverage of documented behavior
  2. Structural techniques (branch coverage, MC/DC) — coverage of implementation paths
  3. Error guessing — coverage of known error patterns the above miss

Each layer catches different bugs:

  • BVA catches off-by-one at documented boundaries
  • Error guessing catches division by zero, SQL injection, and floating-point rounding
  • Neither catches logic errors in the requirements themselves — that's use case testing and reviews

A practical division: use formal techniques for your test design document (the "planned" test cases). Use error guessing for your exploratory testing sessions (the "unscripted" part). Keep both.

Error Guessing in Exploratory Testing

Exploratory testing is simultaneous test design and execution — you learn about the system as you test it, and you use what you learn to decide what to test next. Error guessing is one of the primary heuristics that drives exploratory testing sessions.

The SFDIPOT heuristic (Structure, Function, Data, Interfaces, Platform, Operations, Time) is a common framework for exploratory sessions. Error guessing applies to each dimension:

  • Data: What weird values can I try? (boundary, null, overflow, Unicode)
  • Interfaces: What if I bypass the UI and call the API directly?
  • Operations: What if I do the operation twice? Out of order? Concurrently?
  • Time: What if I leave it running for 24 hours? What if I change the system clock?

Experienced testers move through these dimensions quickly during an exploratory session, applying domain-specific error patterns from their mental catalog.

Checklists: Institutionalizing Error Guessing

The best teams don't rely on individual testers remembering all error patterns. They build checklists.

A checklist is a curated list of error guesses that applies across multiple features. Examples by category:

Input field checklist (applies to any text input):

  • Empty string
  • Spaces only
  • Maximum length boundary
  • Maximum + 1 length
  • SQL injection: '; SELECT * FROM users; --
  • HTML injection: <img src=x onerror=alert(1)>
  • Null byte: input containing \0
  • Long repeating string: AAAA... × 10,000

Date field checklist:

  • Today's date
  • Yesterday, tomorrow
  • January 1 (year boundary)
  • December 31 (year boundary)
  • February 28, March 1 (non-leap year)
  • February 29 (leap year, e.g., 2024)
  • February 29 (non-leap year, e.g., 2023) — should reject
  • Epoch: 1970-01-01
  • Far past: 1900-01-01
  • Far future: 2099-12-31
  • Two-digit year: 99 (ambiguous: 1999 or 2099?)

API endpoint checklist:

  • Missing required field
  • Extra unexpected field
  • Wrong type for each field (string instead of int, etc.)
  • Null for each field
  • Empty string for each field
  • Missing authentication
  • Expired authentication
  • Another user's authentication token
  • Large payload (1MB body)
  • Replay attack (same request twice)

Checklists accumulate over time. A new QA engineer on the team uses the checklist and immediately applies years of accumulated experience they don't yet have personally. That's the value: error guessing knowledge doesn't walk out the door when a tester leaves.

Tracking Error Guesses and Outcomes

After running error guesses, record the results:

Error Guess Feature Outcome Bug?
0-byte file upload Photo upload 500 error with stack trace Yes — BUG-4421
SVG with JS Photo upload Rendered as HTML, XSS Yes — BUG-4422
Upload × 2 concurrent Photo upload Both succeed, second overwrites Questionable — logged
Progressive JPEG Photo upload Pass No
CMYK color space Photo upload Upload succeeds, display broken Yes — BUG-4423

This log serves multiple purposes:

  1. Demonstrates test coverage to stakeholders
  2. Creates institutional knowledge about where bugs were found
  3. Feeds back into the checklist (SVG XSS found → add to checklist permanently)
  4. Shows patterns: if 3 of 5 bugs were found in photo upload, the upload component is high-risk

When to Use Error Guessing

During exploratory testing sessions: Error guessing drives what to try next.

After formal test design: Formal techniques cover the documented behavior; error guessing covers the undocumented gaps.

When reviewing someone else's design: "Did they test concurrent submissions?" is an error guess applied to a test plan review.

For regression testing additions: When a bug is found, add the specific error pattern that found it to the regression suite. A bug found by error guessing is evidence that the error pattern belongs in formal testing permanently.

During API integration testing: Integration points are where different systems' assumptions collide. Error guessing at integration points (what does the upstream send that the downstream doesn't expect?) finds the bugs that unit tests can't.

The Bottom Line

Error guessing is not "just trying random stuff." It's the systematic application of accumulated knowledge about where software fails. The testers who find the most bugs in the least time aren't lucky — they've built a large mental catalog of error patterns, they apply that catalog deliberately, and they document what they find.

The technique scales: a junior tester with a good checklist outperforms a senior tester working from memory alone. Build the checklists, share them, update them when bugs are found. Turn individual intuition into team knowledge.

Start now free