When I review a set of test cases someone's written from experience alone, the pattern is almost always the same. They've tested a normal case, a clearly wrong case, and maybe one thing that looked tricky. What's usually missing isn't obvious in the moment, and that's exactly the problem: it takes a structured technique to see it, not more experience.
Equivalence partitioning
Group inputs into classes that should behave the same way, then test one representative from each class instead of every possible value. A field accepting ages 18 to 65 has three real classes: below range, in range, above range. Testing 20, 35, and 50 all inside the "valid" class tells you nothing new after the first one. Testing one value from each class covers the actual logic with a fraction of the effort a tester defaults to without thinking about it this way.
Boundary value analysis
Most real defects cluster at boundaries, not in the middle of a range,
because off-by-one errors are one of the most common logic mistakes in
condition checks. If the valid range is 18 to 65, test 17, 18, 65, and 66,
not 40. That's four test cases instead of one, and they're the four that
actually catch the < versus <= bug that a middle-of-the-range value never
would.
Writing test cases from experience alone and still missing the edges?
Intuition tests what feels risky, not what's mathematically risky, and boundary defects cluster exactly where that gap shows up. We bring structured design techniques into a manual testing process that's letting bugs through.
Decision tables for combined conditions
When several independent conditions interact, discount eligibility, access permissions, a pricing rule with multiple qualifying factors, a table is the only reliable way to see every combination that needs a check. Writing test cases for combined logic freehand almost always misses at least one combination, because holding four independent booleans and their sixteen combinations in your head at once isn't something intuition is built for. A table makes the gap visible before you've written a single test.
State transition testing
Some features are defined by states more than inputs: an order that moves from pending to paid to shipped, an account that can be active, suspended or closed. Draw the states and the allowed transitions, then test each allowed transition and the invalid ones that matter. Can a cancelled order still be shipped? Can a suspended account still log in? Testing each state on its own never finds those bugs.
Pairwise testing for many options
When a feature has many independent settings, say browser, language, plan and payment method, testing every combination is rarely possible. Pairwise testing picks a small set of cases that covers every pair of values at least once. NIST research on real software failures found that most were triggered by one or two settings interacting, so pairwise sets catch most of them with a fraction of the cases. Free tools like PICT generate the set for you.
Using these techniques in an agile team
Apply them during backlog refinement, not after development. Writing the boundary values and the decision table into the acceptance criteria turns "handle invalid ages" into something a developer can build against and a tester can check. It's the same idea behind shift-left testing, applied to test design.
Where I don't bother
I don't reach for these on a simple CRUD form with one obviously valid path and one obviously invalid one. Building a full decision table for a form with two straightforward fields slows the team down for no real gain. These techniques earn their cost on actual branching logic: pricing, permissions, state machines, anything where the number of paths through the logic is larger than what a person can hold in their head while writing cases from memory.
The output of boundary analysis, specifically the boundary values themselves, is also exactly what should be feeding your test data strategy: if your test data doesn't include the edge values these techniques identify, you're back to the same gap with extra steps. And a test suite built around these techniques is one of the things we look at when a team's manual testing process has more bugs slipping through than the test case count would suggest it should.