ScreenshotNeo

BlogGuides

Test Case Design Techniques: A Practical Guide

Learn how to derive focused test cases with equivalence partitions, boundaries, decision tables, and state transitions—and combine them for real features.

By the ScreenshotNeo team4 October 202610 min read

To design test cases systematically, first model the behavior you need to check, then choose a technique that matches its shape: use equivalence partitioning for groups expected to behave alike, boundary value analysis for ordered limits, decision tables for interacting conditions, and state-transition testing when history changes what an event should do. These techniques complement one another; a single feature may need several.

A test design technique derives tests from a basis or model. It is not a complete test strategy, and a representative test does not prove that every similar value is defect-free. The ISTQB Foundation Level material presented by ASTQB describes these four black-box techniques and distinguishes them from broader black-box, white-box, and experience-based approaches. See ASTQB’s technique overview and its overview of test technique categories.

1. Start with the behavior and choose a model

Before writing individual cases, extract what the system accepts, rejects, calculates, displays, or changes. Identify the observable result and the conditions that affect it. Then pick the model that makes omissions easiest to see.

Technique Use it when Derive cases from Watch for
Equivalence partitioning (EP) Values are expected to receive the same treatment in groups Representatives from valid and invalid partitions Uncovered or overlapping classes; unjustified assumptions that all class members behave identically
Boundary value analysis (BVA) Partitions are ordered and defects may cluster around limits Boundary values and adjacent values, using a two-value or three-value variant Wrong inclusivity, wrong increment, or a boundary that was never identified
Decision table testing Combinations of conditions determine an action or outcome Relevant condition combinations and their expected rules Missing combinations, contradictory outcomes, or omitted conditions
State-transition testing The current state and events determine permitted behavior States, events, guards, transitions, and resulting actions Invalid transitions, unreachable states, and paths that matter but are not covered

These are black-box techniques: they derive expectations from specified behavior without requiring knowledge of internal implementation. Add structural or experience-based testing when code structure, operational knowledge, or tester insight reveals risks the specification model does not capture. The four techniques are not a universal ranking; choose based on the requirement, risk, and coverage goal.

2. Use equivalence partitioning for input classes

Equivalence partitioning divides a data domain into non-overlapping, non-empty groups that are expected to be processed alike. Partitions can describe inputs, outputs, configuration, time values, internal values, or interface parameters. They may be ordered or unordered, discrete or continuous.

Worked example: an age field

Suppose a requirement accepts whole-number ages from 18 through 120 inclusive. The initial partitions are:

  • Invalid: ages below 18.
  • Valid: ages 18 through 120.
  • Invalid: ages above 120.

Choose one representative from each partition, such as 10, 35, and 130, and verify the expected result for each. This is a starting design, not a claim that testing three values proves all values in each class behave alike. Requirement details can imply further partitions: missing input, malformed text, decimals, negative values, or values that cannot be represented by the interface. Add those only when they are in scope and specify expected handling.

How to find useful partitions

  1. List each input or output and its specified constraints.
  2. Split values when the expected behavior changes: valid versus invalid, accepted format versus rejected format, entitled versus not entitled.
  3. Check that every relevant value belongs to a class, with no overlaps between classes.
  4. Select representative values that are meaningful and easy to diagnose.
  5. Record the assumption behind each class. If two values within it may trigger different rules, split it further.

3. Add boundary value analysis at ordered limits

BVA focuses on edges of ordered partitions. It is useful where a threshold can be misplaced, omitted, or treated with the wrong inclusive/exclusive rule. The Foundation Level material describes two-value and three-value BVA. The examples below use whole-number ages, so the adjacent increment is one year.

Variant Lower limit Upper limit Example set
Two-value Test the boundary and the adjacent value outside it Test the boundary and the adjacent value outside it 17, 18, 120, 121
Three-value Test below, on, and above the boundary Test below, on, and above the boundary 17, 18, 19, 119, 120, 121

For the 18–120 inclusive requirement, 18 and 120 should be accepted; 17 and 121 should be rejected. Three-value testing adds 19 and 119 to check just-inside behavior too. Confirm the actual requirement before deriving expected outcomes. Do not assume the step is one: a currency amount may use cents, a date may use a day, and a continuous measurement may require a domain-specific precision or tolerance. If the domain is not ordered, BVA does not fit it.

EP and BVA work well together: partitioning identifies the groups and their limits; BVA concentrates additional cases around those limits. A partition representative far from an edge can still be useful for ordinary valid behavior.

4. Use decision tables for combinations of rules

Decision tables make explicit which combinations of conditions lead to which actions. ASTQB’s presentation of ISTQB Foundation Level material states: “Decision tables are used for testing the implementation of requirements that specify how different combinations of conditions result in different outcomes.” Source: ASTQB, Foundation Level black-box techniques.

For a hypothetical checkout rule, assume a discount applies only when the customer is a member and the order is at least $100. A compact decision table is:

Rule R1 R2 R3 R4
Member? No No Yes Yes
Order at least $100? No Yes No Yes
Apply discount? No No No Yes

Derive at least one test for each relevant rule column, setting up the conditions and checking the stated action. If a condition has more than two meaningful values, list them explicitly rather than squeezing them into yes/no. For example, an account status could be active, suspended, or closed, with different outcomes.

Review a decision table

  • Does every condition that can affect the result appear?
  • Are combinations mutually understandable and outcomes unambiguous?
  • Are any combinations impossible? Mark them rather than treating them as ordinary tests.
  • Can equivalent rules be combined without losing a required distinction?
  • Are boundary values in the conditions tested separately where a threshold is involved?

A decision table can expose a missing requirement as well as derive tests. If a condition combination has no defined outcome, resolve the expected behavior before treating it as a test failure.

5. Use state transitions when history matters

State-transition testing models states and the events that move the system between them. A transition may have a guard condition and may perform an action; a common notation is event [guard] / action. Test cases exercise transitions or paths through the model according to the behavior and risk that matter.

Consider a simple sign-in lockout model:

  • Ready: sign-in is allowed.
  • Locked: sign-in attempts are blocked until the specified recovery event.

Repeated failed attempts may move Ready to Locked when a threshold is reached; a successful sign-in may reset the failure count; a recovery event may move Locked back to Ready. The exact threshold, reset behavior, and recovery rules must come from the product requirement—this example does not prescribe them.

To derive tests, write each state, event, guard, and expected next state/action. Include valid transitions and, when relevant, events that should be rejected or have no effect in a state. Then create paths that establish the necessary starting state and exercise the transition. A test that sends a recovery event is incomplete if it does not first establish Locked.

Choose coverage based on risk and the behavior to protect. State coverage asks whether relevant states were visited; transition coverage asks whether relevant transitions were exercised; path coverage considers sequences of transitions. Longer or cyclic systems may have too many possible paths for exhaustive enumeration, so select paths that represent important risks and specify the coverage goal rather than implying completeness.

6. Combine techniques in a practical workflow

  1. Read the requirement. Identify observable results, constraints, rules, states, and events.
  2. Select the model. Use classes for like-treated values, ordered boundaries for limits, tables for condition combinations, and transitions for history-dependent behavior.
  3. Write the model first. List partitions, edges, rule columns, or states and transitions before choosing concrete data.
  4. Derive cases. Give each case a precondition, input or event, expected result, and requirement/model element it checks.
  5. Review omissions. Look for invalid inputs, adjacent values, missing combinations, unreachable states, and unclear expected outcomes.
  6. Prioritize. Spend more attention on high-risk behavior and important failure consequences. Do not imply exhaustive coverage when the chosen model or selected paths are limited.
  7. Supplement where needed. Add code-structure analysis or experience-based exploration when specification-derived cases leave relevant risks unexamined.

Small case record example

Case: AGE-LOWER-BOUNDARY
Requirement: whole-number age is accepted from 18 through 120 inclusive
Precondition: age form is open
Input: 18
Expected: form accepts the value and continues
Model element: lower valid boundary

Case: AGE-BELOW-LOWER-BOUNDARY
Precondition: age form is open
Input: 17
Expected: value is rejected with the specified validation behavior
Model element: immediately below lower boundary

Keep expected results specific enough to distinguish acceptance, rejection, state changes, and user-visible outcomes. If the requirement says only “show an error,” clarify what observable error behavior is expected before relying on the case.

7. Apply the models to a web interface

The same reasoning works for forms, checkout pages, and account flows. For a web form, partition accepted and rejected input formats; test the minimum and maximum values around limits; build a decision table for combinations such as membership and eligibility; and model multi-step flows as states and transitions. A screenshot can help review visible outcomes such as whether a validation message appears, but it cannot by itself establish server-side correctness or prove every rule combination.

For repeatable browser checks, make the page, viewport, wait condition, and test data explicit. Capture after the relevant action and compare the expected visible state. A screenshot is evidence of a rendered page at a moment; pair it with assertions on the underlying response or application state when those are part of the requirement.

8. Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request captures a URL as PNG, JPEG, WebP, or PDF. It is useful when test cases need a repeatable visual capture without setting up a browser runner. It does not replace assertions about business logic, server responses, or state transitions.

Example with cURL:

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://example.com \
  -o shot.webp

Python:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://example.com"},
    timeout=90,
)
r.raise_for_status()
with open("shot.webp", "wb") as image:
    image.write(r.content)

Node.js:

const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://example.com'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const bytes = new Uint8Array(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', bytes));

See the ScreenshotNeo API documentation for request options. Cookie banners, popups, and chat widgets are removed before capture; each cleanup step can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Every feature is on every plan.

Sign up for 1,000 free screenshots a month, with no card required.

9. Troubleshooting test design

Symptom Likely cause Fix
Many cases look redundant Partitions may not reflect distinct expected behavior, or the model is too detailed State the expected behavior per class; merge only classes that truly share it, and preserve boundary cases.
A boundary test has no clear expected result The requirement does not say whether the limit is inclusive or what increment applies Resolve inclusivity, precision, units, and tolerance with the requirement owner before deriving the oracle.
A decision table grows rapidly Many conditions have been combined without considering relevance or impossibility Mark impossible combinations, identify conditions that do not affect an outcome, and document the chosen combination coverage.
A state test fails before reaching its target transition The precondition did not establish the required starting state Set up the state through a defined path, or use a controlled fixture whose state is explicit.
Tests pass but a defect remains The selected technique covers only its model and chosen representatives Revisit assumptions, add another applicable model, and consider structural or experience-based techniques.
Visual capture differs between runs The page may still be loading or contain changing content Define a wait condition and stable test data; control viewport and relevant timing, then capture the same state.

10. Performance, reliability, and cost considerations

Test design reduces avoidable duplication by making coverage intent visible, but it does not guarantee fewer defects or a particular test count. Cost depends on the system, risk, test environment, and maintenance needs. Representative selection should be deliberate: removing cases without understanding what model element they cover can create gaps.

For reliability, make preconditions and expected outcomes reproducible, isolate state between cases where practical, and document dependencies such as account status, locale, time, or data setup. For browser evidence, wait for a meaningful condition rather than relying on an arbitrary delay where possible, and distinguish visual rendering checks from functional assertions.

ScreenshotNeo pricing is Free for 1,000 shots/month with no card; Starter is $5 for 3,000; Growth $15 for 15,000; Pro $39 for 60,000; Scale $99 for 250,000; and Business $249 for 1,000,000. Yearly billing gives two months free. Caching has a configurable TTL; cache hits are not billed. Account for image format, capture frequency, and whether repeat captures should use cache when planning usage.

FAQ

Are equivalence partitioning and boundary value analysis the same?

No. Partitioning groups values by expected behavior; boundary analysis selects tests around the edges of ordered groups. Boundary tests often complement partition representatives.

Should every possible condition combination be tested?

Not automatically. Identify relevant and feasible combinations, make the coverage choice explicit, and give priority to outcomes with higher risk.

Can I use state-transition testing for a stateless function?

Use it only if the function’s behavior depends on a modeled state or event history. Otherwise, input classes, boundaries, or condition combinations may fit better.

Do these techniques replace code coverage?

No. They derive tests from behavior models. Structural techniques examine implementation structure and can reveal different gaps.

What should I do when a requirement has no expected result?

Clarify the behavior before treating a test outcome as pass or fail. A test without a defined oracle may expose ambiguity but cannot reliably verify conformance.

Further reading: For a deeper treatment of model-based testing and its relationship to classic techniques, see O’Reilly’s Model-Based Testing Essentials.