Lesson 5 of 11 · Software Testing Fundamentals
Writing Test Scenarios
What a test scenario is, how it differs from a test case and a test condition, and a repeatable method for deriving scenarios from user stories and acceptance criteria.
beginner 10 min read Updated
You will learn to
- Distinguish test scenarios, test conditions and test cases
- Derive positive, negative, edge and end-to-end scenarios from a user story
- Prioritise scenarios by risk and trace them to requirements
Prerequisites
- STLC: The Software Testing Life Cycle
- Test Case Design Techniques
Before you write detailed test cases, you need a map of what to test. A test scenario is one entry on that map: a short statement of a situation or user goal that should be checked, such as “Customer pays for an order with a saved card”. Scenarios let you review coverage with a product owner in ten minutes, long before anyone has written step-by-step instructions. They are also the level at which most real teams, especially Agile ones, actually plan their testing.
This lesson shows how to write scenarios that are useful rather than vague, how they relate to test cases, and a method you can apply to any user story.
Scenario, condition, case: the vocabulary
The terms overlap in everyday use, so it helps to be precise.
| Term | What it is | Example |
|---|---|---|
| Test condition | A testable aspect of the system, identified during test analysis (ISTQB term) | “Discount code validity” |
| Test scenario | A situation or end-to-end flow to verify, usually one line | “Customer applies an expired discount code at checkout” |
| Test case | Preconditions, inputs, steps and expected results for one specific check | TC-042: code SPRING25, expiry yesterday, expected message “This code has expired”, total unchanged |
| Test procedure / script | The ordered steps for running one or more test cases, manual or automated | An automated Playwright spec running TC-040 to TC-045 |
“Test scenario” is not a formal ISTQB glossary term, but it is used universally in job descriptions and interviews. In ISTQB language, scenarios sit between test conditions (from test analysis) and test cases (from test design). One scenario usually expands into several test cases; one condition may appear in several scenarios.
What makes a good scenario
A useful scenario is:
- Specific enough to be checked. “Test the login page” is a heading, not a scenario. “Registered user logs in with a correct email and password” is a scenario.
- Written from the user’s or system’s point of view, describing a goal or a situation, not UI clicks.
- Independent of test data details. “Applies an expired code” rather than “types SPRING25”. The data belongs in the test case.
- Traceable to a requirement, user story or risk.
- Single-purpose. If a scenario contains “and then also”, it is probably two scenarios.
| Weak scenario | Why it is weak | Better |
|---|---|---|
| Check checkout | Too broad; nobody can say when it is done | Guest user completes checkout with a valid card |
| Click Pay and verify | Describes UI actions, not a goal | Payment is declined by the provider and the order is not created |
| Test discount codes work | No situation, no expected outcome | Valid percentage code reduces the subtotal before tax |
| Enter 101 items | Data, not scenario | Customer tries to add more than the maximum quantity per item |
A method for deriving scenarios
Use the same five passes on every story. Each pass asks a different question, which stops you from writing only happy paths.
Pass 1: Happy paths
What are the main ways a user achieves the goal? There is often more than one: pay by card, pay by wallet, pay with a gift card.
Pass 2: Alternative and negative paths
What happens when the user does something wrong or the system says no? Invalid input, missing permission, declined payment, duplicate submission, session expired.
Pass 3: Boundaries and edge conditions
Apply boundary value analysis and equivalence partitioning at the scenario level: minimum and maximum quantities, empty cart, exactly-at-limit values, time-based rules (an offer that ends at midnight).
Pass 4: Integrations and state
What other systems, roles or states are involved? Payment provider timeouts, inventory changing during checkout, an admin disabling a product while it is in someone’s cart, behaviour after a page refresh or with two tabs open.
Pass 5: Non-functional concerns
Which quality characteristics matter for this story? Accessibility of the new form, response time of the search, security of the new endpoint, behaviour on a small mobile screen.
Worked example: apply a discount code
User story: As a shopper, I want to apply a discount code at checkout so that I pay the promotional price.
Acceptance criteria:
- A valid code reduces the order subtotal by its percentage or fixed amount.
- Only one code can be applied per order.
- Expired or unknown codes show an error and the total is unchanged.
- Codes are case-insensitive.
- A code with a minimum spend applies only if the subtotal meets the minimum.
Applying the five passes:
| ID | Scenario | Type | Traces to | Risk |
|---|---|---|---|---|
| TS-01 | Valid percentage code reduces the subtotal | Happy | AC1 | High |
| TS-02 | Valid fixed-amount code reduces the subtotal | Happy | AC1 | High |
| TS-03 | Code entered in a different case is accepted | Happy | AC4 | Medium |
| TS-04 | Expired code is rejected and total is unchanged | Negative | AC3 | High |
| TS-05 | Unknown code is rejected and total is unchanged | Negative | AC3 | Medium |
| TS-06 | Second code cannot be added to an order that already has one | Negative | AC2 | High |
| TS-07 | Minimum-spend code applies when subtotal equals the minimum exactly | Boundary | AC5 | High |
| TS-08 | Minimum-spend code is rejected when subtotal is just below the minimum | Boundary | AC5 | High |
| TS-09 | Removing items after applying a code drops the subtotal below the minimum | State | AC5 | High |
| TS-10 | Fixed-amount code larger than the subtotal does not produce a negative total | Edge | AC1 | High |
| TS-11 | Code applied, page refreshed: discount persists | State | AC1 | Medium |
| TS-12 | Error message is announced to screen readers | Non-functional | AC3 | Medium |
Notice that TS-09 and TS-10 are not stated in the acceptance criteria. Good scenario writing exposes these gaps, and the right response is to ask the product owner, not to guess. “What should happen if the subtotal falls below the minimum after the code is applied?” is exactly the kind of question that prevents a production bug.
Expanding a scenario into test cases
Each scenario becomes one or more test cases once you add data and expected results. TS-07 and TS-08 together might produce:
| Test case | Subtotal | Code minimum | Expected result |
|---|---|---|---|
| TC-071 | 50.00 | 50.00 | Code applied, discount shown |
| TC-072 | 49.99 | 50.00 | Error “Spend 50.00 or more to use this code”, total unchanged |
| TC-073 | 50.01 | 50.00 | Code applied |
The scenario stays stable even when the minimum changes from 50 to 60; only the test case data changes. That stability is why scenarios are a good unit for planning and for discussion with non-testers.
Scenarios in Gherkin
Teams using behaviour-driven development (BDD) often write scenarios in Gherkin, where a Scenario is a concrete example with Given, When, Then steps. A Gherkin scenario is closer to a test case than to the one-line scenarios above, because it includes data:
Feature: Discount codes at checkout
Scenario: Minimum-spend code is rejected just below the minimum
Given my cart subtotal is 49.99
And the code "SAVE10" requires a minimum spend of 50.00
When I apply the code "SAVE10"
Then I see the error "Spend 50.00 or more to use this code"
And my subtotal is still 49.99
Scenario Outline: Codes are case-insensitive
Given my cart subtotal is 80.00
When I apply the code "<code>"
Then a 10% discount is applied
Examples:
| code |
| SAVE10 |
| save10 |
| Save10 |
Scenario Outline with an Examples table is the Gherkin way to express one scenario with several data variations. The Gherkin Formatter tidies indentation and table alignment.
Prioritising scenarios
You will rarely have time to turn every scenario into a detailed test case. Rank them by risk, which combines likelihood of failure and impact if it fails:
- High likelihood: new code, complex logic, recently changed areas, integrations, areas with a history of defects.
- High impact: money, data, security, legal obligations, the main user journey.
High-risk scenarios get detailed test cases and usually automation. Medium-risk scenarios might be covered by a checklist or an exploratory session. Low-risk scenarios may be consciously left out, and you should record that decision.
Common mistakes
- Only happy paths. Negative and state-based scenarios find most of the interesting bugs.
- Copying acceptance criteria one to one. Acceptance criteria are a starting point; scenarios should probe what the criteria do not say.
- Scenarios that are really steps. “Click Apply” is a step inside a test case.
- No traceability. Without a link to a story or requirement, you cannot tell which scenarios to update when the story changes. An RTM helps.
- Writing them after development. Scenarios written during refinement shape the acceptance criteria; scenarios written afterwards only check them.
Practice exercise
A banking app has this story: “As a customer, I want to transfer money between my own accounts so that I can manage my balances.” Acceptance criteria: the amount must be greater than 0 and no more than the available balance of the source account; the daily transfer limit is 5,000; source and destination must be different; the transfer appears immediately in both accounts’ history.
Write at least ten scenarios covering all five passes, with a type, the criterion they trace to, and a risk rating. Mark any scenario that reveals a gap in the acceptance criteria. The Test Scenario Generator can give you a starting list to compare against, but write your own first.
Show a model answer
| ID | Scenario | Type | Traces to | Risk |
|---|---|---|---|---|
| TS-01 | Customer transfers a valid amount between two of their accounts | Happy | AC1, AC4 | High |
| TS-02 | Transfer appears in history of both accounts immediately | Happy | AC4 | High |
| TS-03 | Transfer of exactly the available balance succeeds | Boundary | AC1 | High |
| TS-04 | Transfer just above the available balance is rejected | Boundary | AC1 | High |
| TS-05 | Transfer of 0 or a negative amount is rejected | Negative | AC1 | High |
| TS-06 | Transfer that reaches exactly 5,000 for the day succeeds | Boundary | AC2 | High |
| TS-07 | Transfer that would take the day’s total above 5,000 is rejected | Boundary | AC2 | High |
| TS-08 | Same account selected as source and destination is rejected | Negative | AC3 | Medium |
| TS-09 | Double-clicking Confirm does not create two transfers | State | AC1 | High |
| TS-10 | Network drops after Confirm: no money is lost or duplicated | Integration | AC4 | High |
| TS-11 | Amount with more than two decimal places is handled | Edge | Gap | Medium |
| TS-12 | Daily limit resets at midnight in which time zone? | Edge | Gap | Medium |
| TS-13 | Transfer form is usable with keyboard only | Non-functional | Gap | Medium |
Gaps to raise with the product owner: decimal precision (TS-11), the time zone and exact moment the daily limit resets (TS-12), and whether pending transfers count towards the limit. TS-09 and TS-10 are high risk because they involve money and are classic sources of duplicate-transaction bugs, even though no acceptance criterion mentions them.
Key takeaways
- A test scenario is a one-line situation or goal to verify; a test case adds preconditions, data, steps and expected results.
- Derive scenarios in passes: happy, negative, boundary, integration and state, non-functional.
- Good scenarios are specific, goal-oriented, data-independent and traceable.
- Scenario writing is a requirements review technique: the gaps you find are often the most valuable output.
- Prioritise by likelihood and impact, and record what you deliberately leave out.
Key terms
Finished this lesson?
Progress is saved in this browser. No account needed.