Boundary Value Analysis
Test the edges of equivalence partitions. Bugs cluster at boundaries — off-by-one errors, fencepost mistakes, and incorrect comparisons (< vs ≤) almost always appear at the exact limit.
1 The Hook
An Harbour Bank online savings product offers a bonus interest rate when the monthly balance stays at $1,000 or above. A team builds the feature and tests it with a tidy round figure: $5,000 in the account, bonus applied, looks great. Ship it.
A month later a customer complains. They held exactly $1,000 all month and got no bonus. The developer had coded the check as balance > 1000 instead of balance >= 1000 — an off-by-one slip. Every customer sitting on precisely the threshold was quietly short-changed. The test with $5,000 could never have caught it, because $5,000 is nowhere near the edge where the bug lives.
This is the pattern behind a huge share of real defects: the logic is right in the middle of the range and wrong at the exact limit. A value picked from the comfortable middle of a partition tells you nothing about the boundary. The bug was always going to be at $1,000, $999, or $1,001 — and those were the three values nobody tested.
Boundary Value Analysis means testing the values right at and just outside the edges of a valid range — not the comfortable middle — because off-by-one coding errors (< vs ≤) only produce wrong behaviour at the exact limit. Use it whenever a spec defines an ordered range with a minimum or maximum: numbers, dates, string lengths, file sizes, or any ordered domain. The mistake most testers make is testing the boundary itself but skipping the "just outside" value — yet that adjacent value is the only one that can catch a silent accept-when-it-should-reject bug that bypasses UI validation via API or data import.
The failure mode nobody warns you about: your BVA test cases are perfectly correct, and they still miss the bug. I have seen this in NZ financial systems repeatedly. You design a set for a field accepting whole-number percentages 3 to 10, you test 2, 3, 10, and 11 — textbook. Then you discover the database column is a DECIMAL(5,2), so 2.5 is a valid value that slips straight through both boundaries and corrupts the downstream calculation. Before you write a single boundary value, ask the developer one question: what is the actual data type? Integer, float, decimal, string coerced at runtime? The data type determines where the real boundaries sit. In two decades of reviewing test suites across banking and government projects here, the "I tested the UI integer field but the API accepts floats" gap is the most common reason a technically correct BVA set still ships a defect.
2 The Rule
Defects cluster at the edges of a range, not in the middle — so for every boundary, test the value on the boundary and the value just across it (2-value), or the value below, on, and above it (3-value).
3 The Analogy
The height sign at a theme-park ride.
A ride at Rainbow's End has a sign: "You must be 120 cm to ride." The interesting arguments never happen with a kid who is obviously tall or obviously tiny — they happen with the child measured at exactly 120 cm, or 119, or 121. That is where the rule is tested in the real world: right at the line. Does "120 cm to ride" mean 120 gets on, or 120 is too short? The sign's wording (the spec) decides, and that exact point is where staff get it wrong.
Boundary value analysis is standing at the height sign and measuring the three kids right around the line, instead of waving through the obviously-tall ones. The edge is where the rule either holds or breaks.
Common Mistake vs What Works
Testing only a mid-range value and the obvious out-of-range values — for a field accepting 1–100, you test 0 (invalid), 50 (valid), and 101 (invalid) and call it done. No test ever touches 1 or 100. The bug living at the exact boundary is invisible.
Test the boundary itself and the value on each side: 0 (invalid), 1 (valid lower bound), 2 (valid), 99 (valid), 100 (valid upper bound), 101 (invalid). Six tests instead of three — and if the developer wrote > instead of ≥, tests at 1 and 100 are the only ones that will catch it.
What it is
Boundary Value Analysis (BVA) is an extension of Equivalence Partitioning. Once you have your partitions, instead of picking a value in the middle, you test the values at and around the boundary between partitions.
Why boundaries? Developers tend to make off-by-one errors. A spec that says "accept 18–65" might be coded as > 18 instead of >= 18 — a bug that only appears at exactly 18.
2-value BVA (ISTQB standard)
For each boundary, test two values: the boundary itself, and the value just beyond it.
- For a range 18–65: test 18 (in), 17 (out), 65 (in), 66 (out).
3-value BVA (robust)
Test three values at each boundary: the value just below, the boundary itself, and the value just above.
- At lower boundary (18): test 17, 18, 19
- At upper boundary (65): test 64, 65, 66
3-value BVA gives stronger coverage but doubles your test count. Use it when the boundary logic is critical or complex.
Real-world NZ Example: KiwiSaver Eligibility
In New Zealand, to join KiwiSaver independently (without legal guardian consent), you must be 18. You can begin withdrawing your savings at 65. Using 2-value BVA, your test cases are:
- 17: Invalid (just below independent age)
- 18: Valid (minimum independent age)
- 64: Valid (just below withdrawal age)
- 65: Valid (minimum withdrawal age)
- 66: Valid (above withdrawal age — still eligible to contribute, but state contribution stops)
Worked example
Password length field: minimum 8 characters, maximum 20 characters.
| Value | Length | Boundary? | Expected |
|---|---|---|---|
| "passwor" | 7 | Just below min | Rejected |
| "password" | 8 | Minimum boundary | Accepted |
| "12345678901234567890" | 20 | Maximum boundary | Accepted |
| "123456789012345678901" | 21 | Just above max | Rejected |
Combined with EP: BVA gives you boundary tests; EP gives you mid-range tests. Together they cover: one value per valid partition (EP), the boundaries of each partition (BVA), and one representative invalid value per invalid partition (EP). This is standard practice at junior level and above.
ISTQB mapping
| Syllabus ref | Topic | Level |
|---|---|---|
| 4.2.2 | Boundary Value Analysis | CTFL Foundation |
| FL-4.2.2 K3 | Apply 2-value BVA to derive test cases | Foundation LO |
| FL-4.2.2 K3 | Apply 3-value BVA to derive test cases | Foundation LO |
Common mistakes
- Forgetting the "just outside" value — testing only the boundary itself misses off-by-one errors.
- Mixing BVA and EP carelessly — BVA tests the boundary; EP tests the middle. Don't conflate them.
- Non-numeric boundaries — BVA applies to anything ordered: dates, string lengths, list sizes, file sizes, priority levels.
- Inclusive vs exclusive confusion — always check whether the spec says "<" or "≤" before choosing your boundary values.
4 Industry Reality
- Requirements rarely name the boundary type. Specs written by business analysts say things like "must be at least 18" without clarifying whether 18 itself is valid. You will chase down the developer, a legal document, or the product owner to settle inclusive vs exclusive — and the answer sometimes changes late in the sprint.
- Legacy systems have undocumented implicit boundaries. A payment-processing system at an NZ bank might silently cap transaction amounts at $99,999.99 — not because the spec says so, but because a database column was defined as DECIMAL(7,2) fifteen years ago. Senior testers probe these limits even when they are not in the requirements.
- Time pressure turns BVA into "test the happy path near the boundary." When a sprint is overloaded, junior testers test 3, 10, and maybe 2 — they skip 11 because "surely the UI blocks that." It doesn't. The just-outside value is exactly what QA exists to test.
- Non-numeric boundaries catch everyone out. Date boundaries — Revenue NZ filing windows, CoverNZ claim deadlines, KiwiSaver lock-in periods — are where off-by-one bugs are hardest to spot manually. A test that passes on 30 June fails on 1 July. Testers who learn BVA on number fields often forget to apply it to date comparisons.
- The "just outside" value is the most argued test case. Developers regularly push back: "no real user would enter 10,001." That is irrelevant — the system has a defined rule at 10,000, and every boundary has a failure mode waiting for an adversarial input, an integration that passes unexpected data, or a migration that shifts values by one.
Senior engineer insight
The scenario that changed how I use BVA happened on an Revenue NZ late-filing penalty feature. We had a textbook 2-value set — $47,999, $48,000, $48,001 — all passing. Six months later a batch payroll import silently filed returns at exactly $48,000.00 and the penalty fired incorrectly because a downstream rounding step converted the database DECIMAL(10,2) to a float, pushing the value to $47,999.9997 — just inside the safe partition. The boundary test passed at the API layer but the real defect lived one step further down in the pipeline. After that I started tracing every boundary through the full data path: input → validation → storage → calculation → output. The edge that matters is the one closest to the business rule, not the one closest to the form field.
The most common mistake I see from graduates: they test the boundary on the UI and stop there — never realising the API, import job, or calculation layer is operating on a different data type at a slightly different boundary.
From the field
We were testing an CoverNZ weekly compensation calculator that applied a levy band change at the $104,000 annual earnings threshold — a real CoverNZ boundary that determines which employer levy rate applies. The team had tested $103,999 and $104,001 through the UI form and both passed. Three months after go-live, a batch payroll run for a client with exactly $104,000 in earnings fired the wrong levy rate, costing the client $340 in incorrect deductions. The root cause: the UI rounded the entered value to two decimal places before submission, but the batch import sent the raw figure as a float, hitting a floating-point representation just below $104,000.00 — landing in the wrong partition. From that point on, every CoverNZ and Revenue NZ threshold test in our test plan explicitly lists both the UI path and the API/batch path as separate test cases, with the data type confirmed at each layer before we sign off coverage.
5 When to Use It — and When Not To
✓ Use it when
- The field has a clearly defined numeric, date, or ordered range (minimum, maximum, or both)
- The spec uses comparison language: "at least", "no more than", "between X and Y", "minimum", "maximum"
- The boundary represents a business rule with consequences — KiwiSaver eligibility, TransitNZ vehicle limits, Revenue NZ thresholds, age gates
- You need to catch off-by-one coding errors (< vs ≤) in numeric or date comparisons
- You are already doing Equivalence Partitioning — BVA is always the natural next step once partitions are defined
✗ Skip it when
- There is no ordered range — boolean flags, free-text fields without length limits, unordered enums (e.g. dropdown of NZ regions) have no meaningful boundary to test
- The input is already fully validated by a UI control that makes out-of-range values physically impossible to enter (and you have confirmed there is no API bypass)
- Multiple interacting variables mean the boundary shifts dynamically — use Decision Table or pairwise testing instead
- You are writing smoke tests or a quick sanity check — BVA is a coverage technique, not a fast-path validator
- The range has hundreds of valid discrete values and the business risk is low — a single mid-partition EP value is enough
Context guide
How the right level of Boundary Value Analysis effort changes based on project context.
| Context | Priority | Why |
|---|---|---|
| Regulated government or financial system (Revenue NZ, CoverNZ, Benefits NZ, RBNZ) | Essential | An off-by-one at thresholds like the $48,000 Revenue NZ penalty cutoff or CoverNZ’s $104,000 annual-earnings levy band has direct legal and financial consequences; 3-value BVA at the API layer is non-negotiable. |
| Enterprise banking or insurance product (KiwiSaver, home-loan LVR, insurance claim limits) | High | Numeric boundaries (contribution rates 3–10%, LVR caps, date windows for policy inception) appear in almost every flow; boundary bugs here trigger complaints, refunds, and audit findings. |
| Legacy system migration (replatforming a payroll, billing, or fee-calculation engine) | High | Column-type changes (DECIMAL(7,2) to FLOAT) silently shift implicit boundaries; run BVA against the old and new systems at every documented threshold and compare outputs, not just UI behaviour. |
| Agile sprint — story with a numeric or date range acceptance criterion | Medium | Add the two just-outside values to the Definition of Done for any story with a stated minimum or maximum; 2-value BVA fits within sprint cadence, but skip 3-value unless the boundary is business-critical. |
| Early-stage startup with frequently changing business rules | Medium | Apply 2-value BVA to validated, stable boundaries (e.g. a field length limit or age gate); skip exhaustive BVA on thresholds that are still changing — invest the time in exploratory testing and risk discovery instead. |
| Low-risk UI-only feature with no API exposure (search filters, display settings, pagination) | Low | When the boundary is purely cosmetic (e.g. showing 10–100 results per page) and there is no downstream calculation or data-path bypass, a single EP mid-range value is usually enough — spend saved time on riskier flows. |
Trade-offs
What you gain and what you give up when you choose Boundary Value Analysis.