BugMojoBugMojoBugMojo
FeaturesPricingBlogHelpAbout
Add to ChromeLog inGet started
BugMojoBugMojo

Bug reports that actually help fix bugs — capture, replay, share.

A product of Softech Infra.

Product

  • Features
  • Pricing
  • Browser extension
  • Get started
  • Log in

Resources

  • Help & guides
  • Blog
  • Compare
  • Glossary

Company

  • About
  • Contact
  • Security
  • Privacy
  • Terms
  • Sitemap
© 2026 BugMojo. All rights reserved.
AllGuidesEngineeringPlaybooksCompareGlossaryAlternativesBy roleBug tracking by framework
  1. Home
  2. Blog
  3. Guides
  4. How to Write Test Cases (With a Template and Examples)
Guide

How to Write Test Cases (With a Template and Examples)

A good test case is a small, repeatable experiment: given this state, do these steps, expect exactly this result. Here is the standard anatomy aligned with ISO/IEC/IEEE 29119 and ISTQB, a fill-in template, and worked examples.

ManviManvi·Jul 10, 2026·10 min read
Guides
Isometric line-art test case card with rows for ID, preconditions, steps, expected and actual results, the expected-result row glowing lime, on a dark canvas
TL;DR
  • A test case is a small, repeatable experiment. Given a defined state, perform defined steps, and observe whether the system produces exactly the defined expected result.
  • The anatomy is standardized. ISO/IEC/IEEE 29119 and the ISTQB glossary converge on the same fields: ID, title, preconditions, steps, test data, expected result, actual result, status, priority.
  • The expected result is the field people botch. Write it as one observable, unambiguous outcome — not "it works."
  • One behavior per case. Atomic, independent, traceable to an acceptance criterion, and executable by someone who has never seen the feature.
  • When a case fails, capture the actual result — a session replay plus console and network beats a sentence typed from memory.

Most testing advice treats a test case like paperwork — a box QA has to fill so a spreadsheet looks complete. That framing is why so many test cases are useless. A test case is not documentation; it is a small, repeatable experiment. It says: put the system in this state, do these things, and you should see exactly this. If you see something else, the experiment failed and you have found a bug. Everything good about a test case follows from taking that experiment framing seriously.

Two things flow from it. First, repeatability: the same case run twice, by two different people, on two different days, should reach the same verdict. Second, hand-off: the person who executes a case is often not the person who wrote it, so the case has to carry all the context in the text — not in the author's head. This guide walks through the standard anatomy of a test case (aligned with the ISO/IEC/IEEE 29119 series and ISTQB terminology), gives you a template you can copy, shows two fully worked examples, and names the mistakes that quietly wreck a test suite.

Why well-written test cases matter

A test case is a set of preconditions, inputs, and actions with an expected result, written to verify one specific behavior of the system under test. Well-written cases are repeatable, so anyone can execute them and reach the same pass or fail verdict; they give coverage you can measure, and they let one tester hand work to another without loss.

Coverage is the first payoff. When behaviors are written as discrete cases, you can count them, map them to requirements, and see the gaps — the paths nobody is checking. A vague plan that says "test login" hides the fact that nobody ever tried a locked account or an expired session. A list of cases makes the missing ones visible.

Regression protection is the second. The bug you fixed last month comes back; a saved test case is the trap that catches it before your users do. And the third, quietly the most valuable, is hand-off. Testers rotate, contractors leave, and six months from now someone reads your case cold. If it only works when you run it, it isn't a test case — it's a personal ritual. The whole point of the structured fields below is to move the knowledge out of your head and into text that survives you.

The anatomy of a good test case

Both the ISO/IEC/IEEE 29119 test documentation standard and the ISTQB glossary describe the same core fields. Formats differ across tools, but the semantics are stable. Here is each field, what it means, and the trap to avoid.

FieldWhat it means / example
Test Case IDA unique, stable identifier so the case can be referenced, traced, and reported on. Example: TC-LOGIN-001.
Title / ObjectiveOne line naming the single behavior under test. Example: "User logs in with valid credentials." If you need the word "and," you probably have two cases.
PreconditionsThe required state before step 1: the environment, the test data, and the state of the item under test. Example: "A verified account exists (user@example.com / correct password); the user is signed out; the login page is reachable."
Test StepsThe numbered actions to perform, each concrete enough to execute without guessing. Example: 1) Open /login. 2) Enter the email. 3) Enter the password. 4) Click "Sign in."
Test DataThe specific inputs used, separated from the steps so the same steps can be re-run with different data. Example: email user@example.com, password Correct-Horse-9.
Expected Result — the one that matters mostExactly one observable outcome, stated so precisely that pass or fail needs no judgment. Not "login works" but "the user lands on /dashboard, sees their name in the header, and no error is shown." This is the field testers most often write vaguely, and vagueness here poisons the whole case.
Actual ResultWhat actually happened when the case was executed. Filled at run time. When it differs from expected, this becomes your bug evidence.
StatusPass or Fail (some teams add Blocked / Not Run). Determined by comparing actual against expected — nothing else.
PriorityHow important this behavior is (e.g. High / Medium / Low), used to decide execution order under time pressure. A valid-login case is High; an obscure edge case may be Low.
1If you remember one thing: the expected result is a contract, not a hope. "It should work" is not a result anyone can grade. "User lands on /dashboard with their name in the header" is.

A worked example: login, positive and negative

Abstract fields only click when you see them filled in. Here are two cases for the same feature — one positive (valid credentials should succeed) and one negative (wrong password should fail gracefully) — written the way you would actually hand them to another tester.

FieldTC-LOGIN-001 (positive)TC-LOGIN-002 (negative)
TitleUser logs in with valid credentialsLogin is rejected with a wrong password
PriorityHighHigh
PreconditionsVerified account exists; user is signed out; /login is reachableSame verified account exists; user is signed out; /login is reachable
Test Datauser@example.com / Correct-Horse-9user@example.com / Wrong-Password-1
Steps1. Open /login 2. Enter the email 3. Enter the password 4. Click "Sign in"1. Open /login 2. Enter the email 3. Enter the wrong password 4. Click "Sign in"
Expected ResultUser is redirected to /dashboard within 2s; their display name appears in the header; no error is shown; a session cookie is setUser stays on /login; an inline error "Email or password is incorrect" is shown; no session cookie is set; the password field is cleared
Actual Resultfilled at run timefilled at run time
StatusPass / FailPass / Fail

Notice how much is nailed down. The negative case does not just say "login fails" — it specifies how it should fail: the same page, a specific error message, no session cookie, and a cleared password field. That precision is what turns a fuzzy "it errored" into a gradeable outcome. A tester who has never seen this app can run either case and produce the same verdict you would, which is exactly the repeatability and hand-off property we started with.

Positive, negative, and edge cases

Good coverage means testing more than the happy path. Three flavors do most of the work:

  • Positive cases confirm the system does what it should on valid input and supported paths — the login that succeeds, the form that saves, the payment that clears.
  • Negative cases confirm the system fails gracefully on invalid input — wrong password, malformed email, expired token — rejecting the input and showing the right error instead of crashing or silently allowing it.
  • Edge cases probe boundaries: the empty field, the maximum-length string, zero, the exact limit value, the leap-second, the duplicate submit. Bugs cluster at boundaries, which is why the 29119-4 test design techniques (like boundary value analysis and equivalence partitioning) exist to derive them systematically rather than by gut feel.

A feature is not really covered until it has all three. Most teams over-invest in positive cases and under-invest in the negative and edge ones — which is precisely where the escaped bugs live.

Common mistakes that wreck test cases

Common mistake
  • Vague expected results. "It works" or "correct behavior" cannot be graded. State one observable outcome.
  • Steps that assume context. "Log in and go to settings" hides five actions and a precondition. Spell them out.
  • One case testing five things. When it fails you can't tell which behavior broke, and you can't re-run just the broken part.
  • No preconditions. A case that only passes because of leftover state from the last test is a case that will lie to you.
  • Untraceable to a requirement. If a case doesn't map to an acceptance criterion, nobody knows why it exists or whether it still should.

The unifying theme is that all five mistakes move knowledge out of the written case and into the author's memory — which defeats the entire purpose. A case that only you can execute is not a test case; it is a note to yourself. Write for the stranger who will run it after you have moved teams.

Best practices

Five habits separate durable test suites from decaying ones:

  • One behavior per case. If the title needs "and," split it. Atomic cases give precise failure signals and let you re-run only what broke.
  • Atomic and independent. A case must not depend on another case having run first. Set up its own state in preconditions; clean up after itself. Independent cases can run in any order, in parallel, and in isolation.
  • Executable by someone else. The acid test: hand it to a colleague who has never seen the feature. If they can run it without asking you a question, it is written well.
  • Traceable to acceptance criteria. Every case should answer "which requirement does this verify?" This is where testing meets the spec: cases derive from acceptance criteria, so if you write sharp criteria up front, the cases almost fall out of them. See our guide on writing acceptance criteria that prevent bugs for the front half of this pipeline.
  • Keep them alive. A test case is a living asset. When the feature changes, the case changes with it; a suite full of stale cases is worse than no suite, because it manufactures false confidence.

When a case fails: make the actual result real

Here is the moment that connects test cases to everything downstream. A case fails — actual result does not match expected — and now a developer has to fix it. The single biggest determinant of how fast that fix happens is the quality of the Actual Result field. And most testers fill it in the weakest possible way: a sentence typed from memory. "Got an error on submit." Which error? What was on the network? What state was the app in? The developer is now debugging your prose instead of the bug.

The fix is to make the Actual Result a captured artifact, not a recollection. Instead of describing what you saw, attach the reproduction itself: a session replay of the exact steps, the console log at the moment it broke, and the network requests that were in flight. That is precisely what BugMojo does — one click on a failed case captures the rrweb DOM replay, console, and network, so the Actual Result field is the real reproduction, complete by construction. The developer opens the ticket and watches the failure happen instead of interrogating you about it. A well-written test case tells you what should happen; a captured failure tells the developer exactly what did — and together they close the loop from spec to fix without anyone reconstructing anything from memory.

Key takeaway

A test case is a repeatable experiment: defined preconditions, defined steps and data, and one unambiguous expected result. Keep each case atomic, independent, executable by a stranger, and traceable to an acceptance criterion. Write the expected result as a contract, not a hope. And when a case fails, don't type the actual result from memory — capture it, so the developer inherits the real reproduction instead of your recollection.

⁓ ⁓ ⁓
Turn failed test cases into fixable bugs

When a test case fails, capture the Actual Result the way it deserves — a session replay plus console and network in one click, attached and ready for a developer or an AI agent over MCP.

Install the free extension

Frequently asked questions

Frequently asked questions

Sources

  1. ISO/IEC/IEEE 29119 — the international software testing standard series; test documentation templates live in Part 3, test design techniques in Part 4 — Wikipedia (2026)
  2. ISO/IEC/IEEE 29119-1:2022 — general concepts of software testing, the vocabulary and framework the rest of the series builds on — ISO (2022)
  3. ISTQB Glossary — the standard definitions of 'test case', 'precondition', and 'expected result' used across the testing profession — ISTQB (2026)
  4. ISO/IEC/IEEE 29119-4 — test design techniques: specification-based, structure-based, and experience-based methods for deriving test cases — IEEE (2021)
Share:
Manvi
Manvi· QA Tester

Manvi is a Quality Assurance Tester with three years of experience. For her, quality is not just about finding bugs — it is about ensuring the best possible experience for every user.

On this page

  • Why well-written test cases matter
  • The anatomy of a good test case
  • A worked example: login, positive and negative
  • Positive, negative, and edge cases
  • Common mistakes that wreck test cases
  • Best practices
  • When a case fails: make the actual result real

Get bug-tracking insights, weekly.

Engineering deep-dives, QA playbooks, and honest tool comparisons. No spam — unsubscribe in one click.