Static Testing · EP & BVA (numeric & non-numeric) · Decision Tables · State Transition
→ next slide | ESC overview
1. Two families of testing
2. Static techniques — find bugs without running
3. Dynamic black-box — EP, BVA
4. Decision Tables
5. State Transition Testing
Static testing finds bugs before code runs — often 10× cheaper to fix.
Both families complement each other; neither replaces the other.
Reviewing this function as a pull request — what would you flag?
// Rental Car — calculates total price
function calcPrice(days, ratePerDay) {
var total = days * ratePerDay
if (days > 7)
total = total - total * 0.1 // 10% discount
return total
}
var — use const/letTools that analyse source code automatically — no human reviewer needed.
Most CI/CD pipelines run a linter and a security scanner on every pull request. Your code never ships if the static checks fail.
Grey-box = some knowledge of internals. Common in API testing and security testing.
"Divide inputs into groups where every value in the group should behave the same way. Test one value per group."
EP reduces the number of test cases without reducing coverage.
If one value in a partition fails, they all likely fail.
If one passes, they all should pass.
Valid partition — inputs the system should accept and process normally
Invalid partition — inputs the system should reject
Boundary — the exact edges (covered by BVA, next slide)
Requirement: youth discount applies to passengers aged 6–17. Age must be a whole number.
Requirement: only .pdf, .jpg, .png files may be uploaded. All other types must be rejected.
Partitions can be categories, file types, roles, formats — any set of inputs that should behave identically. One test value per partition is enough.
Requirement: password must be 8–20 characters. Spaces not allowed.
"Bugs love boundaries. Test the exact edge values — on, just below, and just above."
EP tells you which partition to test.
BVA tells you which specific values to use.
Bugs are most common where one partition meets another — developers often use < vs ≤ incorrectly.
For each boundary: test the last value inside the partition and the first value outside.
For the range 6–17: test 5 & 6 (lower boundary) and 17 & 18 (upper boundary).
Rule: ages 6–17 get youth ticket. Full price otherwise.
Lower boundary (6):
Upper boundary (17):
age > 6 instead of age >= 6. Age 6 gets adult price. Only a boundary test catches this.Requirement: bookings can only be made for today or a future date. Past dates must be rejected.
Boundary: today's date (lower bound of the valid range)
Also test inside the valid range:
Dates, strings, and ordered categories all have boundaries. Yesterday vs today is just as much a boundary as 17 vs 18.
Think: "what value sits right at the edge of valid/invalid?"
Requirement: rentals over 7 days get a 10% discount. Exactly 7 days pays full price.
// Buggy implementation — which boundary value catches this?
if (days >= 7)
total = total * 0.9;
"When multiple conditions combine to produce different outcomes — use a table."
Decision tables are perfect for business rules.
Each column is one combination of conditions.
You test every combination (or a prioritised subset).
Rule: user logs in with email + password. Account may be locked. All three conditions affect the outcome.
| Condition / Action | TC 1 | TC 2 | TC 3 | TC 4 | TC 5 |
|---|---|---|---|---|---|
| Valid email? | ✗ | ✓ | ✓ | ✓ | ✓ |
| Correct password? | — | ✗ | ✓ | ✓ | ✗ |
| Account locked? | — | — | ✗ | ✓ | ✓ |
| Outcome | Email error | Wrong pwd | Login OK | Locked msg | Locked msg |
5 test cases cover all meaningful combinations. Each column becomes one test case in your test suite.
Rules: loyalty member gets 5% off · Over 7 days gets 10% off · Both discounts can stack.
| Condition / Action | TC 1 | TC 2 | TC 3 | TC 4 |
|---|---|---|---|---|
| Loyalty member? | ✗ | ✓ | ✗ | ✓ |
| Over 7 days? | ✗ | ✗ | ✓ | ✓ |
| Discount applied | None (full price) | 5% off | 10% off | 14.5% off |
TC 4: stacked discounts. Is 14.5% correct (5% then 10% on remainder) or 15% (5+10%)?
The table forces you to ask the business. Ambiguity found before coding saves days of rework.
Rules: orders over €50 get free shipping · New customers get a welcome coupon · Both can combine.
| Condition / Action | TC 1 | TC 2 | TC 3 | TC 4 |
|---|---|---|---|---|
| Order > €50? | ✗ | ✓ | ✗ | ✓ |
| New customer? | ✗ | ✗ | ✓ | ✓ |
| Free shipping? | No | Yes | No | Yes |
| Welcome coupon? | No | No | Yes | Yes |
With 2 conditions each having 2 values → 2² = 4 combinations. Always check: are all combinations realistic?
"Systems move through states. Test that every transition happens correctly — and that invalid transitions are blocked."
Use when the system's behaviour depends on its current state plus an event or input.
Common in: login flows, order lifecycles, booking systems, device firmware.
Rule: 3 failed logins locks the account. Correct login resets the counter.
A rental booking moves through defined states from creation to completion.
| From state | Event | Expected result | Invalid? |
|---|---|---|---|
| Completed | cancel | Error — cannot cancel | ✗ Invalid |
| Active | confirm | Error — already active | ✗ Invalid |
| Confirmed | pick-up | Moves to Active | ✓ Valid |
Order states in a typical online shop — each with allowed and blocked transitions.
Can you refund a Placed order? (Should be blocked)
Can you ship a Cancelled order? (Blocked)
Does Placed → Processing → Cancelled prevent shipment?
These are the tricky edges that bugs hide in.
| Technique | Best for | Output |
|---|---|---|
| Peer Review | Any work product before testing | Issue list |
| EP | Inputs with clear valid/invalid ranges | Representative test values |
| BVA | Numeric ranges, off-by-one errors | Edge-case test values |
| Decision Table | Multi-condition business rules | One test case per column |
| State Transition | Systems with distinct states & flows | Valid + invalid transition tests |
Real testers combine techniques — EP+BVA together, Decision Tables for business rules, State Transition for workflow validation.
Manual techniques →
Automation gives you
Discount logic for a vacation photo print website:
const customer = { isRegistered: false, isBirthday: false }
const order = { photoCount: 3, hasFrames: false }
console.log(calculateDiscount(customer, order))
function calculateDiscount(customer, order) {
let discount = 0;
if (customer.isRegistered) {
if (customer.isBirthday) {
discount = 8;
} else {
discount = 5;
}
}
if (order.photoCount > 10) { discount += 3; }
if (order.hasFrames) { discount += 3; }
return discount;
}
Two test cases are already written:
if-branches if it helps visualise the workflow!
You now have the full toolkit: requirements analysis, test documentation, bug reporting, and all major test design techniques.
Lesson 5 starts the automation track — same techniques, automated execution.
← L3 Bug Reports | L5 Unit Testing & Automation →