How to Write Test Cases
A test case is a precise, repeatable instruction: given these preconditions, do these steps with this data, and expect this result. Written well, it lets any tester — or an automation script — verify one behaviour the same way every time and tells a developer exactly how to reproduce a failure. Written badly, it is a vague sentence that passes on Monday and fails on Tuesday for reasons nobody can name.
This guide gives you the structure of a good test case, a template you can paste into Jira, TestRail or a spreadsheet, a worked example, and the design techniques that turn a requirement into a small set of cases with real coverage.
The fields every test case needs
- ID — a stable identifier (TC-LOGIN-004) so the case can be referenced from bugs and reports.
- Title — one line that names the behaviour, not the feature: "Login rejects a wrong password with a clear message", not "Login test".
- Preconditions — the state the system must be in before step 1: an existing verified user, an empty cart, a specific role.
- Test data — the exact values used, or a pointer to a generated data set. "A valid email" is not test data; "layla.h@example.com" is.
- Steps — numbered, one action each, written so a new hire could follow them.
- Expected result — what must be observed after the last step, specific enough to be checked: status code, message text, record state.
- Priority and type — smoke, regression, negative, boundary — so suites can be filtered.
- Traceability — the requirement, user story or acceptance criterion the case covers.
A test case template
ID: TC-LOGIN-004
Title: Login rejects a wrong password with a clear message
Priority: High Type: Negative
Requirement: US-12 (User can sign in with email and password)
Preconditions: A verified account exists for layla.h@example.com
Test data: email = layla.h@example.com, password = WrongPass!9
Steps:
1. Open /login
2. Enter the email and the wrong password
3. Click "Sign in"
Expected result:
- The page stays on /login
- The message "Email or password is incorrect" is shown
- No session cookie is set; the failed attempt is counted
Postconditions: Account is not locked (attempt 1 of 5)Test scenario vs test case
A test scenario is a one-line statement of what to test — "Verify login with valid and invalid credentials". A test case is the detailed script that tests one path of that scenario. One scenario usually expands into several cases: valid login, wrong password, unknown email, locked account, empty fields. Start with scenarios to agree on scope, then write cases for the paths that matter.
Design techniques that find real bugs
- Equivalence partitioning — group inputs that the system should treat the same (ages 18–65) and test one value per group instead of every value.
- Boundary value analysis — most defects live at the edges. For a field that accepts 1–100, test 0, 1, 2, 99, 100 and 101.
- Decision tables — when several conditions combine (member? coupon? over £50?), a table of every combination guarantees no rule is forgotten.
- State transition testing — for anything with a lifecycle (order: created → paid → shipped → refunded), test every allowed transition and the forbidden ones.
- Negative testing — wrong types, missing fields, special characters, very long input, concurrent actions, expired sessions.
- Pairwise testing — when there are too many parameter combinations, cover every pair of values with a fraction of the cases.
Try it: Boundary Value Generator Try it: Equivalence Partition Generator Try it: Decision Table Generator Try it: Negative Test Generator
From a user story to test cases
Start from the acceptance criteria. Each Given/When/Then statement is at least one positive case; each "should not" or "must" hides a negative one. Then add the boundaries of every field the story mentions, one case for each user role that touches the feature, and one for what happens when a dependency (payment provider, email service) fails. A story with three acceptance criteria typically yields eight to fifteen cases.
Try it: User Story → Test Cases Try it: Acceptance Criteria Generator Try it: AI Test Case Generator
Common mistakes
- Testing several things in one case — when it fails, nobody knows which part broke.
- Vague expected results ("works correctly", "error shown") that cannot be judged pass or fail.
- Steps that depend on another case having run first, so the suite cannot be run in any order.
- Test data that is real customer data — use generated data that is realistic but synthetic.
- Writing only the happy path. Most production incidents are negative or boundary cases.
- Never pruning: cases for removed features and duplicates make regression runs slow and untrusted.
Try it: Test Data Factory Try it: AI Duplicate Test Case Detector
Frequently asked questions
What is the difference between a test case and a test scenario?
A scenario describes what to test in one line; a test case is the step-by-step script for one path through that scenario, with data and an expected result.
How many test cases should a feature have?
Enough to cover each acceptance criterion, each boundary of each input, each role and the main failure modes — usually 8–15 for a typical user story. Coverage of behaviours matters more than the count.
Should test cases include test data?
Yes, or a reference to a generated data set. Without exact values a case is not repeatable and failures are hard to reproduce.
What format do Jira, TestRail and Xray expect?
All of them import CSV with columns for title, preconditions, steps, expected result and priority. Keep one step per row when the tool supports step tables.
Can AI write test cases?
AI can draft a strong first set from a user story or requirement, including negative and edge cases that reviewers often skip. A tester should still review each case for business context and remove anything that does not apply.
How do I write test cases for an API?
The same structure applies: the steps are requests, the test data is the payload and headers, and the expected result is the status code, response body and any state change. See the API testing guide for a full method.
Tools mentioned in this guide
Generate structured test cases (id, title, preconditions, steps, expected result, priority) from a feature description and field list.
Generate high-level test scenarios covering functional, negative, security, usability and compatibility angles for a feature.
Convert a user story (As a / I want / So that) into structured test cases using templates and heuristics.
Generate negative test cases for form fields and APIs: empty, null, wrong type, too long, injection, invalid format.
Generate boundary values (min-1, min, min+1, nominal, max-1, max, max+1) for numeric and length constraints.
Derive valid and invalid equivalence classes for each input and pick representative test values.
Build decision tables from conditions and actions, generate all rule combinations and collapse impossible ones.
Generate Given/When/Then acceptance criteria and a definition-of-done checklist from a user story.
Turn a user story into professional, structured test cases (ID, title, type, priority, preconditions, data, steps, expected result) with Mutqan AI.
One-stop factory for synthetic test data: users, customers, companies, addresses, numbers, dates and strings in JSON, CSV, SQL or XML.