All articles

Test Case Design Techniques: 6 Methods with Real Examples

Learn equivalence partitioning, boundary value analysis, decision tables, state transition, pairwise testing and error guessing, with worked examples and Playwright code.

11 min read

Test DesignSoftware TestingBoundary Value AnalysisPlaywrightISTQB

You can't test every input. A single amount field that accepts values up to 5,000 with two decimal places already has half a million valid values, before you count letters, negative numbers, empty strings and pasted emoji. Multiply that by browsers, payment methods and account states, and exhaustive testing is impossible.

Test case design techniques solve this. They give you a systematic way to pick the small set of test cases that is most likely to find defects, and to explain to anyone on the team why those cases, and not others, are enough.

This guide walks through the six techniques I use most on real projects, all applied to the same example so you can see how they fit together. At the end there is a Playwright example that turns the results into automated tests.

The example we'll use: a deposit form

Imagine the deposit screen of a payments or online gaming app. The requirements say:

  • The deposit amount must be between 10.00 and 5,000.00, with at most two decimal places.
  • A user's deposits are limited to 10,000.00 per day.
  • First-time depositors who are identity-verified (KYC) and deposit at least 20.00 get a welcome bonus. Unverified users can't deposit at all.
  • A withdrawal moves through the states Requested → Under review → Approved → Paid, and can be Rejected during review or Cancelled by the user before approval.

These four rules are typical: a numeric range, a cumulative limit, a business rule with several conditions, and a workflow. Each one calls for a different technique.

Quick comparison of test design techniques

Technique Best for In our example
Equivalence partitioning Inputs with ranges or categories Deposit amount, payment method
Boundary value analysis Numeric limits, lengths, dates 10.00 and 5,000.00 limits
Decision table testing Rules that combine several conditions Welcome bonus eligibility
State transition testing Workflows, statuses, lifecycles Withdrawal states
Pairwise testing Many parameters with several values each Browser × OS × payment × language
Error guessing Gaps the specification never mentions Double-click on "Deposit"

The first five are black-box techniques: you design tests from the requirements without looking at the code. They are also the core techniques in the ISTQB Foundation syllabus, so they come up often in QA interviews.

1. Equivalence partitioning

Equivalence partitioning splits all possible inputs into groups (partitions) that the system should treat the same way. If one value in a partition works, the others should too, so you test one representative value per partition instead of thousands.

For the deposit amount:

Partition Valid? Representative value
Below the minimum No 4.50
Within range Yes 250.00
Above the maximum No 7,200.00
More than two decimal places No 25.505
Negative No -50.00
Not a number No "fifty"
Empty No (blank)

Seven test cases cover a field that would otherwise need millions.

Two rules make this technique effective:

  • Test invalid partitions one at a time. If you enter a negative amount with three decimal places and get an error, you don't know which rule rejected it. One invalid partition per test case keeps failures easy to diagnose.
  • Look for hidden partitions. Requirements rarely mention decimals, signs or empty input, but the code still has to handle them. Ask "what other kinds of input could arrive here?" for every field.

2. Boundary value analysis

Defects cluster at the edges of partitions. Developers write > instead of >=, or validate the minimum on the front end but not in the API. Boundary value analysis (BVA) tests the values right at and next to each boundary.

The key detail is the step size. For a whole-number field the step is 1. For a currency field with two decimals, the step is 0.01, which is the most common mistake I see in test cases: testing 9 and 11 around a minimum of 10 misses the bug where 9.99 is accepted.

Boundary Just below On the boundary Just above
Minimum 9.99 ✗ 10.00 ✓ 10.01 ✓
Maximum 4,999.99 ✓ 5,000.00 ✓ 5,000.01 ✗

Using the values on and just outside each boundary (two-value BVA) gives four test cases: 9.99, 10.00, 5,000.00 and 5,000.01. Add the "just inside" values (three-value BVA) when the risk is high, such as anything involving money.

Boundaries aren't only on input fields. The 10,000.00 daily limit is a boundary too: a user who has already deposited 9,990.00 today should be able to deposit 10.00 more, and be blocked at 10.01. Dates and times have boundaries as well. What happens to the daily limit at midnight, and in which time zone?

3. Decision table testing

When the outcome depends on a combination of conditions, testing each condition separately isn't enough. A decision table lists every combination and the expected result for each.

For the welcome bonus, there are three conditions:

Rule 1 2 3 4 5
KYC verified No Yes Yes Yes Yes
First deposit – Yes Yes No No
Amount ≥ 20.00 – Yes No Yes No
Deposit allowed No Yes Yes Yes Yes
Bonus applied No Yes No No No

Three yes/no conditions give eight combinations. Because unverified users can't deposit at all, the other two conditions don't matter in rule 1 ("–" means "any value"), which collapses four combinations into one. The result is five test cases, one per rule.

Decision tables also expose gaps in the requirements. Writing this one forces the question: is a deposit of exactly 20.00 eligible? The requirement says "at least 20.00", so yes, which also tells you to add 19.99 and 20.00 as boundary tests.

Use decision tables for discount and pricing rules, permissions and roles, eligibility checks, and any requirement phrased as "if… and… unless…".

4. State transition testing

Some features behave differently depending on what happened before. State transition testing models the feature as states and the events that move it between them, then tests both the valid transitions and the invalid ones.

For withdrawals:

From state Event To state Valid?
Requested Submit for review Under review Yes
Under review Approve Approved Yes
Under review Reject Rejected Yes
Approved Pay out Paid Yes
Requested User cancels Cancelled Yes
Under review User cancels Cancelled Yes
Approved User cancels – No
Paid User cancels – No
Rejected Approve – No

The valid rows show that the workflow works. The invalid rows are where the expensive bugs hide: a user cancelling an approved withdrawal and getting the money back in their balance and in their bank account, or an admin approving a request that was already rejected.

At minimum, cover every valid transition once (0-switch coverage). For critical flows, also test sequences of two transitions, such as reject and then try to approve, which is called 1-switch coverage. Always test invalid transitions through the API as well as the UI: a hidden button doesn't stop someone calling the endpoint directly.

5. Pairwise testing

Suppose the deposit form must work on 3 browsers, 3 operating systems, 4 payment methods and 2 languages. Testing every combination means 3 × 3 × 4 × 2 = 72 test runs.

Pairwise testing (also called all-pairs testing) is based on the observation that most configuration defects are triggered by the interaction of just two parameters, such as "Safari with mobile money" or "French with bank transfer". Instead of every combination, you cover every pair of values at least once.

For these parameters, a pairwise set needs only about 12 runs instead of 72, while still testing every browser with every payment method, every language with every operating system, and so on. You don't need to build the set by hand: tools such as Microsoft's free PICT generate it from a short list of parameters.

Pairwise testing is a risk-based shortcut, not a guarantee. If a combination of three specific values is known to be critical, such as your highest-revenue browser, payment method and country, add it explicitly.

6. Error guessing

The specification never lists every way users and systems misbehave. Error guessing uses experience to target the mistakes software typically makes. For the deposit form, my checklist would include:

  • Double-clicking "Deposit", or pressing Enter twice. Does the user get charged twice?
  • Pressing Back after a successful payment and submitting the form again.
  • Two browser tabs depositing at the same time when the user is close to the daily limit.
  • The session expiring while the payment provider's page is open.
  • Amounts with spaces, commas or a different decimal separator, such as "1 000,50".
  • The payment provider timing out or returning an error after charging the card.

Error guessing works best as a structured complement to the other techniques, not as a replacement. Keep a shared list of past production bugs and reuse it on every new feature. It is one of the most valuable assets a QA team can build.

How to choose the right technique

If the requirement mentions… Start with
Minimum, maximum, length, range, date limits Equivalence partitioning + boundary values
"If… and… or…", eligibility, permissions, pricing Decision table
Status, workflow, lifecycle, "can only… after…" State transition
Supported browsers, devices, locales, integrations Pairwise
Payments, concurrency, retries, third-party calls Error guessing, on top of the others

Most features need more than one. For the deposit form, the combination gives roughly 7 partition tests, 6 boundary tests, 5 decision-table tests, 9 transition tests, 12 pairwise runs and a short error-guessing checklist. That's about 40 targeted checks instead of a test space too large to count, and you can justify every one of them.

Automating boundary tests with Playwright

Design techniques produce tables, and tables map naturally onto data-driven automated tests. Here are the four boundary cases for the deposit amount as a single Playwright spec:

import { test, expect } from "@playwright/test";

const boundaries = [
  { amount: "9.99", accepted: false },
  { amount: "10.00", accepted: true },
  { amount: "5000.00", accepted: true },
  { amount: "5000.01", accepted: false },
];

for (const { amount, accepted } of boundaries) {
  test(`deposit of ${amount} is ${accepted ? "accepted" : "rejected"}`, async ({ page }) => {
    await page.goto("/wallet/deposit");
    await page.getByLabel("Amount").fill(amount);
    await page.getByRole("button", { name: "Deposit" }).click();

    if (accepted) {
      await expect(page.getByText("Deposit request received")).toBeVisible();
    } else {
      await expect(page.getByText("Enter an amount between 10.00 and 5,000.00")).toBeVisible();
    }
  });
}

Each row becomes its own named test in the report, so a failure reads as "deposit of 5000.01 is rejected" rather than a generic error. When the business changes the limit, you update one table.

Boundary and decision-table tests are also good candidates for the API layer: they run in milliseconds, and they prove the server enforces the rule even if the front-end validation is bypassed.

Frequently asked questions

What are test case design techniques?

Test case design techniques are systematic methods for choosing which test cases to write. Instead of guessing, you derive tests from the structure of the requirements (black-box techniques), the code (white-box techniques) or experience (experience-based techniques), so you get the highest chance of finding defects with the fewest tests.

What is the difference between black-box and white-box test design?

Black-box techniques, such as equivalence partitioning and boundary value analysis, use only the requirements and the system's observable behaviour. White-box techniques, such as statement and branch coverage, are based on the code itself and are usually applied in unit tests. Most QA engineers use black-box techniques day to day.

Is boundary value analysis part of equivalence partitioning?

They are separate techniques that work best together. Equivalence partitioning identifies the groups of inputs; boundary value analysis then tests the edges between those groups, where defects are most likely.

Which test design technique is the most effective?

There is no single best technique; it depends on the requirement. Boundary value analysis finds the most defects in numeric and range-based input, decision tables in business rules, and state transition testing in workflows. Combining them gives the best coverage.

Key takeaways

  • Exhaustive testing is impossible, so use design techniques to choose tests deliberately.
  • Equivalence partitioning reduces inputs to one value per group; test invalid groups one at a time.
  • Boundary value analysis tests the edges, using the correct step size (0.01 for currency).
  • Decision tables cover rules that combine conditions and expose gaps in requirements.
  • State transition testing finds the costly bugs in invalid transitions; check them in the API too.
  • Pairwise testing cuts configuration matrices from dozens of runs to a dozen.
  • Error guessing captures what the specification forgot. Keep a list of past bugs.
  • The tables you produce translate directly into data-driven automated tests.

Good test design also makes automation more reliable. When automated checks start failing for no clear reason, read how to fix flaky tests.

Building a test strategy for a payments or high-traffic platform? Get in touch.