Test Plan Enumeration β Equivalence Partitioning (EP) & Boundary Value Analysis (BVA)¶
Covers Round 1, Section 4: "Test Case / Test Plan Enumeration." The interviewer gives a scenario; you must talk out a test plan and produce EP + BVA tables live, naming the techniques explicitly. This file gives you the theory crisp enough to recite, a repeatable recipe, full worked answers to all 4 JD sample questions, the BFSI angle for each, and a reusable test-plan skeleton.
0. How to win this section (read first)¶
The interviewer is grading three things: 1. Do you name the technique? Say the words "Equivalence Partitioning" and "Boundary Value Analysis" out loud, and say why you're using them. 2. Can you produce a table? They want partitions + boundaries with expected results, not a vague list. 3. Do you cover invalid + boundary + non-functional? Juniors only test the happy path. Seniors test invalid classes, off-by-one boundaries, and (for BFSI) money precision, real-time accuracy, security, and PII/KYC validation.
Your opening line for any scenario:
"I'll structure this with two black-box techniques. Equivalence Partitioning to group inputs into classes so I test one representative per class instead of every value β that controls the test count. Then Boundary Value Analysis on the edges of each valid range, because defects cluster at boundaries β off-by-one,
<vs<=. Let me identify the fields first, then build the tables."
1. Equivalence Partitioning (EP) β from scratch¶
Definition (plain words)¶
Equivalence Partitioning divides the input domain of a field into groups (classes) where every value in the group should be treated the same way by the software. If 99 and 100 and 101 all flow through the same code path and produce the same kind of result, they are equivalent β so testing one of them is (in theory) as good as testing all of them.
Valid vs invalid partitions¶
- Valid partition β inputs the system should accept and process normally.
- Invalid partition β inputs the system should reject / error on / handle gracefully.
A common rookie mistake is testing only valid classes. Always enumerate invalid classes too β that's where robustness bugs live. For a numeric "Age 0β120" field:
| Partition | Range | Type | Representative |
|---|---|---|---|
| Below range | < 0 | Invalid | -5 |
| In range | 0β120 | Valid | 45 |
| Above range | > 120 | Invalid | 130 |
| Non-numeric | "abc" | Invalid | "abc" |
| Empty | (blank) | Invalid (if mandatory) | "" |
Why it reduces test count¶
The "Age 0β120" field has 121 valid integers plus infinite invalid values. Exhaustive testing is impossible. EP says: pick one representative per class β ~5 tests give you confidence across the whole domain. It's a coverage-vs-cost trade: fewer tests, still hitting each distinct behavior.
Tiny generic example¶
A login allows passwords 8β16 characters: - Invalid (too short): length 0β7 - Valid: length 8β16 - Invalid (too long): length 17+
One test per class (e.g. 5 chars / 12 chars / 20 chars) covers the partitioning. (EP tells you which classes exist; BVA next tells you which exact values to pick within them.)
EP cautions to mention (sounds senior)¶
- Partitions can be on output too, not just input (e.g. "discount tier 0%, 10%, 20%").
- Some "equivalent" values aren't truly equivalent if hidden sub-rules exist (leap-year Feb 29, special characters). Don't blindly trust the partition β sanity-check.
2. Boundary Value Analysis (BVA) β from scratch¶
Definition¶
Boundary Value Analysis tests the values at and immediately around the edges of each valid partition. EP finds the ranges; BVA hammers the edges of those ranges.
Why bugs cluster at boundaries¶
Developers write conditions like if (age >= 0 && age <= 120). The classic bugs are:
- Off-by-one: < written where <= was meant (so 120 gets rejected, or 121 gets accepted).
- Inclusive/exclusive confusion at min and max.
- Overflow / type limits (e.g. a value just past INT_MAX, or a money field overflowing 2 decimals).
These are the single most common functional defects, which is exactly why BVA is a named, expected technique.
The 2-value variant (min / max edges)¶
For a range [min, max], test:
| Point | Value |
|---|---|
| Just below min | min β 1 (invalid) |
| Min | min (valid) |
| Min + 1 | min + 1 (valid) |
| Max β 1 | max β 1 (valid) |
| Max | max (valid) |
| Just above max | max + 1 (invalid) |
The 3-value variant (a.k.a. "robustness BVA")¶
Some shops teach 3 values per boundary: boundary β 1, boundary, boundary + 1. Applied to both min and max that's the 6-row table above. "2-value vs 3-value" is just a vocabulary question the interviewer may probe β answer: "2-value BVA takes min, min+1, maxβ1, max; 3-value (robustness) BVA adds the just-outside points minβ1 and max+1 to confirm the system rejects them."
Off-by-one focus (the money line)¶
"On any range field I always test the exact boundary and boundary Β± 1, because the highest-probability defect is a
<vs<=off-by-one in the validation condition."
3. The repeatable 4-step recipe (apply to ANY field live)¶
Memorize this. It's what you narrate while you build the table.
Step 1 β List the inputs/fields and their rules. What fields exist? What's the data type, allowed range, length, format, mandatory/optional, dependencies?
Step 2 β Equivalence-partition each field. For every field write its valid class(es) and invalid classes (below, above, wrong type, empty/null, wrong format). Put them in a table with a representative value.
Step 3 β Apply BVA to every ordered/range field. For each range or length limit, add minβ1, min, min+1, maxβ1, max, max+1. Skip BVA for pure categorical fields (no ordering = no boundary).
Step 4 β Add cross-field, negative, and non-functional cases. Decision tables for combinations, state transitions for flows, plus the BFSI non-functional set: money precision/rounding, real-time accuracy, security (injection, auth), performance/latency, accessibility.
Then summarize: scope β test types β entry/exit β data β risks (the skeleton in Β§9).
4. How EP/BVA combine with other techniques (brief)¶
EP/BVA handle single-field input validation. Real systems need combinations and flows:
| Technique | When to use | One-liner |
|---|---|---|
| Decision Table | Multiple inputs combine to drive an outcome (rules engine) | Rows = rules (condition combos), columns = actions. Great for discount eligibility, loan approval, fraud limits. |
| State Transition | Behavior depends on current state + event | Test valid and invalid transitions. Great for order lifecycle, account status (activeβlockedβclosed), KYC pendingβverified. |
| Pairwise / Orthogonal | Many fields, combinatorial explosion | Cover all pairs of values instead of all combinations. |
| Error Guessing | Experience-driven | Leap years, emoji in name, copy-paste with trailing spaces, negative money. |
The senior framing: "EP+BVA validate each field in isolation; I then layer a decision table for field combinations and state transition testing for the flow β together they give input coverage plus behavioral coverage."
5. FULL WORKED ANSWERS β the 4 JD sample questions¶
Q1 β Mobile stock-trading app: real-time stock-price accuracy & reliability¶
Restate scope (say this): "I'm testing a financial-institution mobile trading app, focusing on accuracy and reliability of real-time price updates and the order path that depends on them. I'll EP/BVA the price, frequency, quantity and order-value fields, then cover market-session state and non-functional real-time concerns."
5.1 Fields & rules identified¶
| Field | Rule (assumed for the table) |
|---|---|
| Stock price | > 0, up to 2 decimal places (penny), e.g. 0.01 β 999,999.99 |
| Update frequency | Tick every N ms; expected β€ 1s refresh during market hours |
| Order quantity | Integer 1 β 10,000 (per-order cap) |
| Order value | quantity Γ price; min $1 / max per-txn limit (e.g. $1,000,000) |
| Market session | Pre-open / Open / Closed / Halted |
| Network latency | Acceptable < 500 ms; degraded 500β2000 ms; stale > 2000 ms |
| Decimal precision | Exactly 2 dp, half-up rounding |
5.2 EP β partitions¶
| Field | Valid partition | Invalid partition(s) |
|---|---|---|
| Price | 0.01 β 999,999.99 | β€ 0; negative; > max; > 2 decimals (1.234); non-numeric |
| Quantity | 1 β 10,000 (integer) | 0; negative; > 10,000; fractional (1.5); non-numeric |
| Order value | $1 β $1,000,000 | < $1; > per-txn limit |
| Update freshness | latency < 500 ms (fresh) | 500β2000 ms (degraded/show stale flag); > 2000 ms (stale β block trade) |
| Market session | Open (orders allowed) | Pre-open/Closed (queue or reject); Halted (reject) |
5.3 BVA β boundary tables¶
Price (0.01 β 999,999.99): | Value | Expected | |---|---| | 0.00 | Reject (β€ 0) | | 0.01 | Accept (min tick) | | 0.02 | Accept | | 999,999.98 | Accept | | 999,999.99 | Accept (max) | | 1,000,000.00 | Reject (over max) | | 1.234 | Reject (>2 dp) |
Quantity (1 β 10,000): | Value | Expected | |---|---| | 0 | Reject | | 1 | Accept (min) | | 2 | Accept | | 9,999 | Accept | | 10,000 | Accept (max) | | 10,001 | Reject | | 1.5 | Reject (fractional) |
Order value ($1 β $1,000,000 per-txn cap): test $0.99 (reject), $1.00 (accept), $1,000,000.00 (accept), $1,000,000.01 (reject).
Network latency (price freshness): | Latency | Expected | |---|---| | 499 ms | Show live price, allow order | | 500 ms | Boundary β define behavior (still live) | | 2,000 ms | Show "delayed" flag | | 2,001 ms | Mark stale; block/confirm before order |
5.4 State / real-time cases¶
| Scenario | Expected |
|---|---|
| Place order while Market Open | Accepted, priced at live tick |
| Place order at Pre-open | Queued or rejected per rules |
| Place order while Closed | Rejected with clear message |
| Stock Halted mid-order | Order blocked, user notified |
| Price ticks between quote shown and order submit (slippage) | App re-confirms / honors limit; no execution at stale price |
| WebSocket/stream drops then reconnects | UI shows reconnecting, resumes ticks, no frozen stale price shown as live |
| Rapid ticks (high frequency) | UI doesn't lag/queue stale values; latest wins |
5.5 Non-functional must-haves¶
- Decimal precision/rounding: verify 2 dp half-up; never show 3 dp or floating-point artifacts (e.g. 10.1*3).
- Performance: refresh latency under load; concurrent users; price feed throughput.
- Reliability: failover when price feed goes down β app must NOT display a stale price as current.
- Security: orders authenticated; can't tamper price/quantity in the API request.
5.6 BFSI angle¶
Money math and real-time accuracy are the whole product. A stale price shown as live, or a rounding error in order value, is a financial loss and a regulatory/trust issue. Emphasize: never let stale data masquerade as fresh; verify rounding to the penny; verify per-transaction limits (a risk/compliance control).
Q2 β Hospital patient-registration system: robust data validation¶
Restate scope: "I'm validating the patient-registration form so registration data is captured robustly. I'll EP/BVA each field β name length, age, DOB, phone, email, insurance ID β and separate mandatory from optional fields. This is PII, so format and privacy validation matter."
6.1 Fields & rules¶
| Field | Mandatory? | Rule (assumed) |
|---|---|---|
| First/Last name | Yes | 2β50 chars, letters/space/hyphen/apostrophe |
| Age | Yes (or derive from DOB) | Integer 0β120 |
| DOB | Yes | Valid date, not in future, consistent with age |
| Phone | Yes | 10 digits (national) |
| No (often) | RFC-ish format | |
| Insurance ID | No | alphanumeric, fixed length e.g. 10 |
| Gender | Yes | from set |
6.2 EP β partitions¶
| Field | Valid | Invalid |
|---|---|---|
| Name | 2β50 valid chars | < 2 chars; > 50; digits/special (123, J@n); empty (mandatory) |
| Age | 0β120 | < 0; > 120; non-integer; blank |
| DOB | past valid date | future date; impossible date (31 Feb, 30 Feb); wrong format; blank |
| Phone | exactly 10 digits | < 10; > 10; letters; with symbols (+,-); blank |
| valid format | missing @; missing domain; double @; spaces (if provided) | |
| Insurance ID | 10 alphanumeric | < 10; > 10; special chars (optional β blank is valid) |
6.3 BVA β boundary tables¶
Name length (2β50): 1 (reject), 2 (accept), 3 (accept), 49 (accept), 50 (accept), 51 (reject).
Age (0β120): | Value | Expected | |---|---| | -1 | Reject | | 0 | Accept (newborn) | | 1 | Accept | | 119 | Accept | | 120 | Accept (max) | | 121 | Reject |
Phone (length 10): 9 digits (reject), 10 (accept), 11 (reject). Insurance ID (length 10): 9 (reject), 10 (accept), 11 (reject) β but blank is valid since optional.
6.4 Cross-field & special cases¶
| Scenario | Expected |
|---|---|
| DOB vs Age mismatch | Flag inconsistency |
| DOB = today (newborn) | Accept, age 0 |
| DOB = leap day 29-Feb-2024 | Accept (valid leap year) |
| DOB = 29-Feb-2023 | Reject (not a leap year) |
| Mandatory field blank | Block submit, field-level error |
| Optional (email/insurance) blank | Allow submit |
| Duplicate patient (same name+DOB+phone) | Warn/merge per policy |
6.5 Non-functional / BFSI-adjacent (healthcare PII)¶
- PII validation & privacy: mask/secure SSN-like IDs; this maps directly to BFSI KYC thinking.
- Security: SQL injection in name (
Robert'); DROP TABLE--), XSS in text fields. - Accessibility: error messages screen-reader friendly, labels present.
- Localization: unicode names (accents, non-Latin), DOB date formats.
6.6 BFSI angle¶
Frame this as KYC/onboarding: validating identity fields (name, DOB, ID number, contact) with strict format rules is exactly what bank customer-onboarding does. Same techniques, same PII-handling discipline (no PII in logs, encrypted at rest, masked on screen).
Q3 β E-commerce discount-code redemption at checkout¶
Restate scope: "I'm testing discount-code redemption at checkout. There are many combining rules β validity, expiry, minimum cart, percent-vs-flat, max cap, stacking, usage limits, rounding β so I'll EP/BVA the individual fields and then use a decision table for the combinations, since eligibility is a rules problem."
7.1 Rules identified (assumed)¶
- Code valid only if active, not expired, usage limit not exceeded.
- Min cart value e.g. $500 to apply.
- % discount (e.g. 20%) with a max cap (e.g. $200), OR flat discount (e.g. $100).
- Stacking typically not allowed (one code per order).
- Currency rounding to 2 dp.
7.2 EP β partitions¶
| Field | Valid | Invalid |
|---|---|---|
| Code | exists & active | doesn't exist; deactivated; wrong case (if case-sensitive); blank |
| Expiry | today β€ expiry | expired (yesterday); not-yet-active (future start) |
| Cart value vs min | β₯ min (eligible) | < min (rejected, prompt "add $X more") |
| Usage limit | uses < limit | uses = limit (block); per-user already redeemed |
| Discount type | % within cap; flat | β |
7.3 BVA β boundary tables¶
Min cart value (min = $500): | Cart | Expected | |---|---| | $499.99 | Reject (below min) | | $500.00 | Accept (boundary) | | $500.01 | Accept |
Expiry date (valid through 30-Jun, time-zone aware): | Date/time | Expected | |---|---| | 30-Jun 23:59:59 | Valid (last second) | | 01-Jul 00:00:00 | Expired | | start date β 1 | Not yet active |
Max discount cap (20% capped at $200): | Cart | Raw 20% | Applied | Note | |---|---|---|---| | $999 | $199.80 | $199.80 | Under cap | | $1,000 | $200.00 | $200.00 | At cap | | $1,001 | $200.20 | $200.00 | Capped |
Usage limit (limit = 100): use #100 (accept), use #101 (reject); per-user limit 1 β 2nd attempt reject.
7.4 Decision table (combination logic)¶
| # | Code active | Not expired | Cart β₯ min | Under usage limit | β Discount applied? |
|---|---|---|---|---|---|
| R1 | Y | Y | Y | Y | Yes |
| R2 | N | β | β | β | No (invalid code) |
| R3 | Y | N | β | β | No (expired) |
| R4 | Y | Y | N | β | No (below min cart) |
| R5 | Y | Y | Y | N | No (limit reached) |
7.5 Rounding & stacking cases¶
| Scenario | Expected |
|---|---|
| 33% off $10.00 = $3.30 (or $3.333) | Round to $3.33 half-up; final = $6.67; cents reconcile |
| Two codes entered | Only one applies (no stacking) per rule |
| Discount > cart value (flat $100 on $80 cart) | Cap discount at cart value; total never negative |
| Apply code, then remove an item dropping cart below min | Re-validate β discount removed |
| Currency precision | Stored/charged amount = displayed amount to the cent |
7.6 BFSI angle¶
This is money math + rules engine β same shape as a bank's fee/interest/cashback calculation. Stress: rounding correctness (sum of rounded line items vs rounded total β the classic $0.01 reconciliation bug), no negative totals, and idempotent application (applying the same code twice doesn't double-discount). These are exactly the controls a banking transaction engine needs.
Q4 β Registration-form INTEGRATION flow (form β API β email β SMS)¶
This is the make-or-break question. Besides EP/BVA on the form, the interviewer wants you to (a) treat it as a chained integration across UI/API/DB/email/SMS, (b) say how you test each hop, and (c) explicitly draw the line between what YOU test vs what another person/team owns (the email-service and SMS-gateway hops). Mocking vs end-to-end is the key judgment.
The flow:
[Web form: firstName, lastName, email, mobile (mandatory) + address (optional) + Submit]
β submit
βΌ
[Backend API: POST /users β creates user, persists to DB]
β on success
βΌ
[Email service: triggers welcome email] (async)
β
βΌ
[SMS service: triggers welcome SMS] (async)
8.1 HIGH-LEVEL TEST PLAN (speak this)¶
- Objective: verify the end-to-end registration flow creates a valid user and reliably triggers welcome email + SMS, with correct validation, contracts, persistence, and async orchestration.
- In scope: UI field validation, API contract (status/schema/idempotency), DB persistence, the triggering of email & SMS, and the orchestration/timing between hops.
- Out of scope (other teams own these β say it explicitly): the email vendor's actual mailbox delivery and rendering, the SMS gateway/telco delivery, deliverability/spam. I test that we correctly call those services with the right payload; the email-platform team / SMS-gateway team validate that the message physically arrives. I verify the contract and the trigger, they verify delivery.
- Approach: layered β (1) UI tests for validation, (2) API tests (REST Assured) for contract + DB, (3) integration tests with the email/SMS services mocked for fast deterministic runs, (4) a thin end-to-end suite against real (or sandbox) services for confidence.
8.2 EP/BVA on the form fields¶
| Field | Valid | Invalid | BVA |
|---|---|---|---|
| First name | 2β50 letters | <2, >50, digits/special, empty | 1/2/50/51 |
| Last name | 2β50 letters | same | 1/2/50/51 |
| valid format | no @, no domain, double @, spaces, empty | local-part/domain length limits | |
| Mobile | 10 digits | <10, >10, letters, +symbols, empty | 9/10/11 |
| Address | any β€ 200 (optional) | >200 | blank = valid (optional); 200/201 |
Mandatory rule: blank firstName/lastName/email/mobile β block submit, field-level error, no API call fired.
8.3 How to test EACH HOP¶
Hop 1 β UI validation (Selenium/Playwright): - Field-level: required-field errors, format errors, max-length, inline messages. - Positive: valid data enables Submit; Submit triggers exactly one POST. - Negative: invalid data shows error and does not call the API. - Accessibility: labels, error announcement, keyboard nav.
Hop 2 β API contract (REST Assured): | Check | Expected | |---|---| | Status code | 201 Created on success; 400 on bad payload; 409 on duplicate | | Response schema | matches JSON schema (id, fields echoed, timestamps) | | Headers | Content-Type, Location of new resource | | Idempotency | same request twice (or with idempotency key) β no duplicate user | | Validation parity | API rejects bad data even if UI bypassed (security: never trust client) | | AuthN/AuthZ | endpoint protected appropriately | | Negative | missing mandatory field β 400 with clear error body |
Hop 3 β DB persistence: - After 201, query DB: user row exists, all fields stored correctly (no truncation, correct encoding for unicode names), optional address null when omitted. - No PII leaked in logs; sensitive fields handled per policy. - Rollback: if email/SMS trigger fails, is the user still created? (Define expected behavior β usually yes, user creation is the source of truth and notifications are async/best-effort.)
Hop 4 β Email service (the contract boundary): - What I test: that on successful user creation, our system publishes the correct trigger to the email service β correct recipient, template id, and personalization payload. Verified via a mock/stub of the email service (e.g. WireMock) asserting the request, OR via the message-queue/event the service consumes, OR an internal "email queued" status/audit record. - What the email-platform team executes: actual rendering, deliverability, bounce handling, mailbox arrival. In E2E I may assert arrival in a test inbox (Mailosaur/MailHog sandbox), but ownership of real-world delivery is theirs.
Hop 5 β SMS service (gateway boundary): - What I test: correct request to the SMS service β right mobile number, right message body, right sender id β verified against a mocked gateway or our outbound audit record. - What the SMS-gateway/telco team executes: actual SMS delivery, carrier routing, DLT/regulatory templates, delivery receipts. I do not own the telco; I own that we call the gateway correctly.
Hop 6 β Orchestration / async timing: | Scenario | Expected | |---|---| | Happy path | user created β email triggered β SMS triggered, within SLA | | Email service down | user still created; email retried/queued; failure logged; SMS still attempted (or per policy) | | SMS service down | user + email succeed; SMS retried; no user-creation rollback | | Slow downstream | API responds to UI promptly (notifications async, not blocking) | | Duplicate submit / double-click | idempotency β one user, one email, one SMS | | Ordering | email/SMS only fire after successful persistence, never before | | Partial failure visibility | monitoring/alerting; retry with backoff; dead-letter for poison messages |
8.4 Mock vs end-to-end (state the strategy)¶
"For fast, deterministic CI I mock the email and SMS services and assert we call them with the correct contract (status, payload, schema) β that isolates our logic. Separately, a small end-to-end suite runs against sandbox/real services with a test inbox and test phone number to validate the full chain periodically. Unit-level field validation is exhaustive; the costly E2E path is a thin smoke layer. The boundary is clear: I verify the trigger and contract; the email and SMS teams verify physical delivery."
8.5 BFSI angle¶
In banking, registration = customer onboarding/KYC, and welcome email/SMS often carries OTP / activation / account credentials β so this flow is security- and compliance-critical. Emphasize: validate server-side (never trust the client), idempotency (no duplicate accounts), audit trail for every notification (regulatory), PII never in logs, and OTP/credential messages must be reliably triggered and traceable even when a downstream service is degraded.
9. Reusable TEST PLAN SKELETON (speak from this for any scenario)¶
Use this structure verbally so your answer sounds like a plan, not a list. Hit each heading in ~1 sentence, then dive into EP/BVA tables.
| Section | What to say |
|---|---|
| 1. Scope / Objective | What feature, what quality goal (accuracy, validation, integration reliability). |
| 2. In scope | Fields, flows, hops you will test. |
| 3. Out of scope | Things other teams own (vendor delivery, telco, infra); 3rd-party internals. |
| 4. Test approach | Black-box: EP + BVA for fields, decision table for combos, state transition for flows; layered UI/API/DB/integration; mock vs E2E. |
| 5. Environments | Dev / QA / Staging / sandbox for 3rd-party services; test data isolation. |
| 6. Test data | Valid/invalid sets per partition, boundary values, PII-safe synthetic data, money edge cases. |
| 7. Entry criteria | Build deployed, env up, test data ready, API contract/spec available. |
| 8. Exit criteria | All planned cases run, critical/high defects closed, coverage of every EP class + boundary, no open Sev-1/2. |
| 9. Types of testing | Functional, integration/contract, security (injection, auth, PII), performance (latency/load), accessibility, regression. |
| 10. Risks & mitigations | 3rd-party flakiness β mock; async timing β retries/idempotency; money precision β rounding tests; real-time staleness β freshness checks. |
10. One-page cheat sheet (glance before the call)¶
- Say the technique names. "Equivalence Partitioning⦠Boundary Value Analysis."
- EP = group inputs into valid + invalid classes; one representative each β fewer tests.
- BVA = test
minβ1, min, min+1, maxβ1, max, max+1; bugs = off-by-one (<vs<=). - Recipe: (1) list fields+rules β (2) EP each β (3) BVA each range β (4) cross-field + non-functional.
- Always add: invalid classes, empty/mandatory, wrong type/format, security, money precision/rounding, real-time freshness.
- Combos β decision table. Flows β state transition.
- Integration Q4: test UI validation, API contract (status/schema/idempotency), DB persistence, and the trigger to email/SMS. You verify contract + trigger; email-platform & SMS-gateway teams verify physical delivery. Mock for CI, thin E2E for confidence.
- BFSI framing every time: money to the penny, real-time accuracy, KYC/PII validation, security, idempotency, audit/compliance.