GUIDE / manual
How to Write Test Cases: Complete Guide with Examples
Learn how to write test cases with practical steps, examples, a QA template, common mistakes, and review tips for reliable software coverage.
A spreadsheet full of steps is not quality insurance if nobody can tell what risk each row protects. How to write test cases is about making product behavior testable, repeatable, and reviewable: condition, action, expected result, and why the check exists.
This guide walks through the full workflow: reading requirements, identifying scenarios, choosing test data, writing clear steps, defining expected results, reviewing coverage, and improving test cases over time. You will also get a worked example, a reusable template, common mistakes, and a practical checklist you can use in real projects.
What Is a Test Case?
A test case is a documented check that verifies whether a specific product behavior works as expected under specific conditions. It usually contains a title, objective, preconditions, test data, steps, expected result, actual result, status, priority, and requirement reference.
Think of a test case as a small contract between the product expectation and the software implementation. If the software follows the expected behavior, the test passes. If it does not, the test gives the tester enough evidence to report a useful defect.
A test case is different from a test scenario. A scenario is a broader idea, such as "user logs in with valid credentials." A test case is the precise execution of that idea, such as "verify that a registered buyer can log in with a valid email and password and lands on the dashboard."
A test case is also different from a bug report. The test case defines the expected behavior before or during testing. The bug report records what actually failed, the steps to reproduce it, the impact, and supporting evidence. If you need help with that next artifact, see the guide on how to write a bug report.
Why Good Test Cases Matter
Good test cases reduce ambiguity. When a tester writes "check login," ten people can interpret that phrase ten different ways. One person might test email login only. Another might test phone number login. Another might include remember me, lockout rules, validation messages, and role based redirects. A test case turns a broad intention into a repeatable check.
Good test cases also improve team communication. Product managers can confirm that acceptance criteria are covered. Developers can understand what behavior will be verified. Automation engineers can identify stable candidates for scripts. Support teams can see how important flows are supposed to behave.
Most importantly, test cases preserve learning. Every release teaches the team something about risk. Maybe users often submit forms with leading spaces. Maybe payment failures are common on slow networks. Maybe mobile browsers expose layout issues that desktop testing misses. When those lessons become test cases, the product becomes harder to break in the same way twice.
Poor test cases create the opposite effect. They look like coverage, but they do not guide execution. They hide gaps, waste review time, and make regression testing slow. A bloated suite with unclear expected results can be worse than a smaller suite of focused, high value cases.
How to Write Test Cases Step by Step
The most reliable way to write test cases is to move from context to risk, then from risk to concrete checks. Do not start with a blank spreadsheet and invent steps randomly. Start with the product behavior.
Step 1: Understand the Requirement
Read the user story, acceptance criteria, design, API contract, business rule, or defect ticket that triggered the testing work. Highlight nouns, verbs, rules, states, roles, limits, and exceptions.
For example, imagine this requirement:
A registered user can reset their password using a verified email address. The reset link expires after 30 minutes. The new password must meet the password policy. After success, the user can log in with the new password and cannot log in with the old password.
From this short requirement, you can identify roles, data states, time limits, validation rules, security behavior, and post success behavior. That is already more useful than starting with "test reset password."
When requirements are incomplete, write questions before writing cases. Ask what should happen for unverified emails, expired links, reused links, locked accounts, weak passwords, rate limits, and email delivery failures. Good testers turn missing information into visible questions.
Step 2: Identify Test Scenarios
List the broad behaviors that need coverage. Scenarios are not detailed steps yet. They are the testing ideas you will later turn into cases.
For the password reset requirement, scenarios might include:
- Reset request with registered verified email.
- Reset request with unknown email.
- Reset link used before expiry.
- Reset link used after expiry.
- New password that satisfies policy.
- New password that violates policy.
- Login with new password after reset.
- Login with old password after reset.
- Reuse of a reset link after success.
Notice that these scenarios cover positive paths, negative paths, boundaries, security checks, and state changes. You can use the same thinking for checkout, search, profile settings, subscriptions, file uploads, or any other product feature.
If you want a deeper technique for choosing boundaries and partitions, read boundary value analysis and equivalence partitioning. Those two methods are especially useful when inputs have ranges, categories, lengths, limits, or validation rules.
Step 3: Prioritize by Risk
Not every scenario deserves the same level of detail. Prioritize based on user impact, business impact, technical complexity, regulatory concern, defect history, and frequency of use.
A password reset success flow is high priority because users can be locked out. Expired link behavior is high priority because it protects account security. Unknown email messaging may be high priority if user enumeration is a security concern. A minor copy variation in an informational message may be lower priority.
Use priority to decide which cases need full manual detail, which can become automated regression checks, which can be sampled during exploratory testing, and which can be deferred.
Step 4: Define Preconditions
Preconditions describe what must be true before the test begins. They prevent confusion during execution.
Examples:
- User account exists and email is verified.
- User is logged out.
- User has access to the email inbox.
- Password policy is active.
- Test environment can send email.
- Current time is within 30 minutes of link generation.
Without preconditions, a valid test case can fail for the wrong reason. If the email service is disabled in the test environment, a reset email test will fail even if the application logic is correct. Good preconditions protect the signal.
Step 5: Choose Test Data
Test data is part of the test case, not an afterthought. Include the exact values that matter.
For login and password reset, this may include email addresses, old passwords, new passwords, account status, and timestamps. For checkout, it may include product type, coupon code, address, payment method, tax region, inventory state, and currency. For file upload, it may include file name, extension, size, MIME type, and file content.
Good test data is realistic enough to expose real problems, but controlled enough to be repeatable. Avoid relying on shared accounts that other testers can change. If a test case requires a unique email address, document the pattern.
Step 6: Write the Steps
Write steps as clear user actions. Use numbered steps. Keep each step observable and executable.
Weak step:
Check forgot password.
Better steps:
1. Open the sign in page.
2. Select Forgot password.
3. Enter reset.user@example.com.
4. Submit the reset request.
5. Open the password reset email.
6. Select the reset link within 30 minutes.
7. Enter ValidPass#2026 as the new password.
8. Submit the reset form.
The better version makes role, data, timing, and expected activity clear. Another tester can repeat it without asking what "check" means.
Step 7: Write Expected Results
Expected results are the heart of the test case. They define what correct behavior looks like.
Avoid vague expectations such as "works fine" or "success message shown." State the observable result.
Better expected results:
- The reset request is accepted without exposing whether the email exists.
- A reset email is delivered to the verified email address.
- The reset link opens the password reset form before expiry.
- The new password is accepted when it satisfies policy.
- The user sees a success confirmation.
- The old password no longer works.
- The new password allows login.
A test case can have one final expected result or expected results after each step. For complex flows, expected results beside each step are clearer. For simple flows, a final expected result may be enough.
Step 8: Add Traceability
Traceability connects the test case to the requirement, user story, risk, or defect that justifies it. This is useful during audits, releases, and regression planning.
Common references include:
- User story ID.
- Requirement ID.
- Acceptance criteria number.
- Defect ID.
- Risk ID.
- Automation test ID.
Traceability also helps when requirements change. If the password policy changes, you can search for all test cases linked to that requirement and update them consistently.
Step 9: Review and Refine
Review test cases before execution when the feature is important. A review can be quick, but it should answer clear questions:
- Does each test case verify one clear behavior?
- Is the expected result specific?
- Are important negative and boundary cases included?
- Is the data realistic and available?
- Are duplicate cases wasting effort?
- Are preconditions clear enough?
- Does the case link to a requirement or risk?
Test case review is where many missed defects are prevented. A developer may spot an invalid assumption. A product manager may clarify a rule. Another tester may add a boundary you missed.
Test Case Template You Can Reuse
Use this template when you need a downloadable style test case format for manual testing, regression testing, or test management tools.
| Field | What to Write | Example |
|---|---|---|
| Test Case ID | Unique identifier | TC-AUTH-001 |
| Title | Short behavior under test | Verify password reset with verified email |
| Requirement Reference | Story, rule, or defect link | US-124 AC-2 |
| Priority | Business or user risk | High |
| Type | Positive, negative, boundary, regression | Positive regression |
| Preconditions | Required state before execution | Verified user account exists |
| Test Data | Exact data to use | reset.user@example.com, ValidPass#2026 |
| Steps | Numbered user actions | Open sign in, request reset, submit new password |
| Expected Result | Observable correct behavior | Password changes and old password fails |
| Actual Result | What happened during execution | Filled during run |
| Status | Pass, fail, blocked, not run | Filled during run |
| Notes | Evidence, environment, issue links | Screenshot, build number |
Here is a copy friendly version:
Test Case ID:
Title:
Requirement Reference:
Priority:
Type:
Preconditions:
Test Data:
Steps:
1.
2.
3.
Expected Result:
Actual Result:
Status:
Notes:
For teams building a larger QA process, connect this template to your broader test planning artifacts. The difference between a plan and a strategy matters because they answer different questions. A test strategy explains the overall approach, while a test plan explains what will be tested for a specific release or project. See test plan vs test strategy when you want to structure the higher level documents around your cases.
Worked Example: Login Test Cases
Let us turn a common login requirement into practical test cases.
Requirement:
A registered user can sign in with a valid email and password. The system validates required fields, rejects invalid credentials, locks the account after five failed attempts, and redirects authenticated users to the dashboard.
Scenario Breakdown
Before writing the table, identify the major behaviors:
- Valid login.
- Missing email.
- Missing password.
- Invalid email format.
- Wrong password.
- Unknown email.
- Account lockout after repeated failures.
- Redirect after successful login.
- Session persistence after refresh.
- Logout and access control after logout.
Example Test Case Table
| ID | Title | Preconditions | Test Data | Steps | Expected Result | Priority |
|---|---|---|---|---|---|---|
| TC-LOGIN-001 | Verify valid user login | User exists and is active | qa.user@example.com, ValidPass#2026 | Open sign in, enter valid email, enter valid password, submit | User lands on dashboard and session is created | High |
| TC-LOGIN-002 | Verify required email validation | User is on sign in page | Password only | Leave email blank, enter password, submit | Email required message appears and login is not submitted | High |
| TC-LOGIN-003 | Verify required password validation | User is on sign in page | Email only | Enter valid email, leave password blank, submit | Password required message appears and login is not submitted | High |
| TC-LOGIN-004 | Verify invalid email format | User is on sign in page | qa.user | Enter invalid email format, enter password, submit | Email format validation appears before authentication | Medium |
| TC-LOGIN-005 | Verify wrong password rejection | Active user exists | Valid email, wrong password | Enter valid email, enter wrong password, submit | Generic invalid credentials message appears and session is not created | High |
| TC-LOGIN-006 | Verify account lockout | Active user exists and has zero failed attempts | Valid email, five wrong passwords | Submit wrong password five times | Account is locked according to policy and further login is blocked | High |
| TC-LOGIN-007 | Verify dashboard redirect | Active user exists | Valid credentials | Log in successfully | User is redirected to the dashboard URL | Medium |
| TC-LOGIN-008 | Verify old session is cleared after logout | User is logged in | Existing session | Select logout, revisit dashboard URL | User is redirected to sign in and protected data is not visible | High |
This table is compact, but each case has a specific purpose. It does not say "test login" eight times. It separates required field validation, format validation, authentication failure, lockout, redirect, and access control.
For practice, open QABattle tracks and choose the manual testing track. Convert one scenario battle into five test cases using this table format. Then compare your cases against the behavior you actually observe.
Positive, Negative, Boundary, and Regression Cases
Balanced test coverage usually includes several test case types.
Positive Test Cases
Positive cases verify that valid user behavior works. They are important because they protect the main path users depend on.
Examples:
- User signs in with valid credentials.
- Customer completes checkout with a valid card.
- Admin exports a report for a valid date range.
- User uploads a supported file type under the size limit.
Positive cases should be clear and stable. They often become smoke tests or automation candidates.
Negative Test Cases
Negative cases verify that the system handles invalid input, invalid state, or invalid permissions correctly.
Examples:
- User signs in with an incorrect password.
- Guest tries to access an admin page.
- Customer enters an expired coupon.
- API request omits a required token.
Negative testing is not about trying random bad data. It is about testing realistic ways users, systems, and attackers can violate assumptions.
For concrete patterns you can adapt, study negative test cases examples before filling a suite with unrealistic invalid data.
Boundary Test Cases
Boundary cases verify values at the edges of allowed ranges.
If a password must be 8 to 64 characters, test 7, 8, 64, and 65 characters. If a search field supports 100 characters, test 0, 1, 100, and 101 depending on the rule. Boundaries often expose defects because developers use comparisons such as less than, less than or equal to, greater than, and greater than or equal to.
Regression Test Cases
Regression cases protect behavior that has worked before, especially after code changes. They often come from important flows, past defects, integrations, and areas touched by recent work.
When a serious bug is fixed, add or update a regression test case. If the bug was caused by missing coverage, the new case should make that gap visible in future releases. Connect the case to the defect ID and keep it in the regression suite if the risk remains.
What Makes a Test Case Good?
A good test case has seven qualities.
First, it verifies one main behavior. If a case tries to test login, profile update, email notification, and logout at the same time, failure analysis becomes difficult. You may still write end to end scenarios, but they should be marked as flows, not atomic functional cases.
Second, it has clear preconditions. The tester should know what account, role, data, environment, and state are required.
Third, it uses precise test data. "Enter invalid data" is weak. "Enter 65 characters in a field with a 64 character limit" is stronger.
Fourth, it has observable expected results. A tester should be able to decide pass or fail without guessing.
Fifth, it is maintainable. Avoid over describing obvious clicks in a way that breaks every time the UI label changes slightly. Focus on intent and important details.
Sixth, it is traceable. The team should know why the case exists.
Seventh, it is reviewable. Another tester should be able to read the case and spot missing logic, duplicate coverage, or unclear expectations.
Common Mistakes When Writing Test Cases
Mistake 1: Writing Steps Without Expected Results
Steps describe what the tester does. Expected results describe what the product should do. A test case without expected results is just a task list.
Bad:
1. Open checkout.
2. Add item.
3. Pay.
Better:
1. Add an in stock item to the cart.
2. Complete payment with a valid test card.
Expected result: Order confirmation appears, inventory is reduced by one, payment status is captured, and the order is visible in order history.
Mistake 2: Mixing Too Many Behaviors
Long cases are sometimes useful for user journeys, but they are hard to debug. If a 25 step case fails at step 21, the root cause may be far earlier. Break complex behavior into focused functional cases plus a smaller number of journey cases.
Mistake 3: Copying Requirements as Test Cases
Acceptance criteria are not automatically test cases. They need data, steps, expected results, and edge thinking. "User can upload a profile image" should become cases for supported format, unsupported format, max size, empty file, preview, save, replace, remove, and permissions.
Mistake 4: Ignoring Negative Paths
Many bugs live outside the happy path. Required fields, invalid formats, permission errors, duplicate actions, network failures, expired sessions, and inconsistent states are all common sources of defects.
Mistake 5: Using Fragile Test Data
If five testers share the same account, one tester can change the password and block everyone else. If a test relies on a product that may go out of stock, the case becomes unstable. Stable data matters for stable execution.
Mistake 6: Writing Cases Nobody Will Maintain
Test cases are living assets. If they are too verbose, duplicated, or disconnected from current behavior, the team stops trusting them. Review and prune old cases. Merge duplicates. Update cases when requirements change.
Mistake 7: Forgetting Defect Learning
Escaped bugs are expensive lessons. When a bug reaches production, ask what test case would have caught it. Then add that case to the right suite. This connects test case design with the full software testing life cycle, from requirement analysis to closure.
Test Case Review Checklist
Use this checklist before sharing a suite for execution:
- The primary user flows are covered.
- Important negative paths are covered.
- Boundary values are covered where ranges or limits exist.
- Each case has a clear title.
- Preconditions are specific.
- Test data is listed and available.
- Steps are numbered and executable.
- Expected results are observable.
- Priority reflects business or user risk.
- Requirement or defect references are included.
- Duplicate cases have been removed.
- Cases that should become automated checks are marked.
- Cases affected by open questions are marked as blocked or pending.
For a stronger practice loop, try a QABattle manual testing challenge from the battle arena. After you submit, rewrite your exploration notes into formal test cases. This trains both discovery and documentation.
How to Keep Test Cases Maintainable
Maintenance is where many test suites fail. Teams write cases during a project, then ignore them until regression testing becomes painful. A maintainable suite needs ownership and pruning.
Start by separating suites by purpose. A smoke suite should contain a small number of critical checks that answer, "Can we continue testing this build?" A regression suite should protect important existing behavior. A feature suite should cover the new change in detail. An exploratory charter should guide investigation without pretending every observation is scripted.
Use naming conventions. Prefix cases with the feature area, such as AUTH, CHECKOUT, SEARCH, PROFILE, or REPORTS. Use titles that explain behavior, not implementation details. "Verify locked user cannot sign in" is better than "Click login button after five wrong attempts."
Mark automation candidates. Stable, repeatable, high value cases are usually good automation candidates. Highly visual, subjective, or one time migration checks may be better as manual cases. Do not automate a bad test case. Clarify the case first.
Review after each release. Remove obsolete cases. Update changed expected results. Add regression cases for important defects. Move low value cases out of critical suites. The suite should get sharper over time, not just larger.
Manual Test Cases vs Automated Test Scripts
Manual test cases and automated scripts are related, but they are not the same artifact.
| Dimension | Manual Test Case | Automated Test Script |
|---|---|---|
| Purpose | Guide human verification and judgment | Execute repeatable checks quickly |
| Strength | Exploratory observation, product context, flexible thinking | Speed, consistency, regression protection |
| Weakness | Slower execution, human variation | Maintenance cost, limited judgment |
| Best for | New features, ambiguous behavior, usability, one time checks | Stable flows, smoke tests, regression checks |
| Output | Pass, fail, blocked, notes, evidence | Assertion result, logs, screenshots, traces |
Start with clear test cases, then automate the ones that are stable and valuable. If the manual case has unclear data or expected results, automation will only make that confusion run faster.
Example: Turning a Bug Into a Regression Test
Imagine a production bug: users could apply the same coupon twice by refreshing the checkout page after the first application.
Weak regression case:
Check coupon refresh bug.
Strong regression case:
Test Case ID: TC-CHECKOUT-REG-014
Title: Verify coupon discount is not duplicated after checkout refresh
Requirement Reference: BUG-892
Priority: High
Preconditions: Cart contains one eligible item, SAVE20 coupon is active, user is on checkout page
Test Data: Product A, SAVE20
Steps:
1. Apply SAVE20 coupon.
2. Confirm the discount is applied once.
3. Refresh the checkout page.
4. Review the order summary.
Expected Result: The coupon remains applied once, the discount amount is not duplicated, and the payable total is correct.
This case preserves the learning from the bug. It includes the exact risk, data, and expected result. It can also become an automated regression script because it is repeatable and has a clear assertion.
Final Practical Workflow
When you need to write test cases for a real feature, use this workflow:
- Read the requirement and acceptance criteria.
- List scenarios before writing detailed cases.
- Add positive, negative, boundary, permission, data, and state based scenarios.
- Prioritize based on user impact and business risk.
- Define preconditions and test data.
- Write numbered steps.
- Write observable expected results.
- Add requirement or defect traceability.
- Review with another tester, developer, or product owner.
- Execute, learn, and update the suite.
The best test cases are not the longest. They are the clearest. They help the team make a reliable decision about product quality. They expose risk without creating noise. They turn requirements, defects, and tester judgment into reusable coverage.
If you remember one rule, remember this: a test case should help a competent tester reproduce the same check and reach the same pass or fail decision. Everything else in the template exists to support that goal.
FAQ
Questions testers ask
What is the best format for a test case?
The best format includes a clear title, objective, preconditions, test data, numbered steps, expected results, actual results, status, priority, and traceability to a requirement or risk. Keep the format consistent so reviewers can compare coverage across features.
How detailed should test case steps be?
Steps should be detailed enough that another tester can reproduce the same action and observation without guessing. Avoid tiny mechanical instructions when the behavior is obvious, but include exact data, state, role, environment, and expected messages when they affect the result.
How many test cases are enough?
Enough test cases cover the important user flows, acceptance criteria, boundaries, negative paths, roles, data states, and known risks. The number depends on risk and complexity, not a fixed quota. A small login change may need ten cases, while checkout may need dozens.
Should every bug have a test case?
Every important escaped bug should usually lead to a regression test case or an automated check. Minor cosmetic bugs may not need permanent coverage, but defects that could return, affect revenue, block users, or damage trust deserve reusable test coverage.
Can AI write good test cases?
AI can draft useful starting points, but a tester must verify coverage, data, expected results, and business risk. AI often misses product context, hidden constraints, and priority. Use it to accelerate brainstorming, then review the cases like any other test artifact.
RELATED GUIDES
Continue the route
Test Plan vs Test Strategy: Templates and Examples
Learn the test plan vs test strategy difference with IEEE 829 sections, document templates, Agile tips, examples, and common mistakes to avoid.
Boundary Value Analysis and Equivalence Partitioning Explained
Learn boundary value analysis and equivalence partitioning with examples, robust BVA rules, interview tips, and how to design sharper test cases.
Bug Report Template: How to Write a Great Defect Report
Learn how to write a bug report with a clear template, steps to reproduce, severity vs priority, expected vs actual results, and examples developers trust.
STLC: The 6 Phases of the Software Testing Life Cycle
Learn the software testing life cycle (STLC) phases with entry and exit criteria, Agile vs Waterfall tips, test closure activities, and practical examples.