Skip to content

Blog

How to Write QA Test Cases: A Practical Guide for QA Engineers

Learn how to write clear, maintainable QA test cases with practical examples, templates, and best practices for manual and modern software testing teams.

QA Workflow Assistant13 min read
  • test-cases
  • manual-testing
  • qa
  • test-design

Clear test cases remain one of the most useful artifacts in software quality work. Whether you are writing manual testing test cases for a release, reviewing coverage for a feature, or converting a user story to test cases, the goal is the same: make expected behavior explicit, repeatable, and easy to review.

This guide shows how to write QA test cases that other engineers can run without guessing. It includes a reusable QA test case template, a complete software test case example for login, and test case writing best practices you can apply on any team—manual, hybrid, or tooling-assisted.

What is a QA test case?

A QA test case is a structured set of instructions that verifies one specific product behavior. It states the conditions that must be true before starting, the data to use, the steps to perform, and the result that should happen when the product is working correctly.

A good test case is not a vague checklist item like “test login.” It is a focused scenario such as “valid user can sign in with email and password and land on the dashboard.” That precision is what makes manual testing test cases transferable between people and still useful weeks later when the feature changes.

Test cases commonly support regression suites, acceptance checks against a user story, handoffs between QA and development, and scripted passes before exploratory testing. They are not a substitute for judgment. They are a shared language for expected behavior.

Why well-written test cases matter

Poorly written cases create noise. Overly detailed ones create maintenance debt. Well-written ones reduce both problems.

They reduce ambiguity

When steps and expected results are explicit, two testers are more likely to exercise the same path and interpret the same outcome. That matters during release pressure, onboarding, and handoffs across time zones.

They improve defect reports

A failed case already contains preconditions, data, and steps. That makes bugs faster to reproduce and easier for developers to trust.

They expose missing requirements

Writing cases forces questions about empty fields, locked accounts, expired sessions, and permission boundaries. Those questions often surface gaps before production.

They scale tribal knowledge

Senior testers often carry product nuance in their heads. A maintainable suite turns some of that knowledge into something the next person can run without a meeting.

They support better coverage decisions

Once cases are structured, it is easier to see whether you covered only the happy path or also included negatives and edges—and to choose lighter or deeper coverage intentionally.

The essential parts of a test case

Most teams do not need twenty fields. They need a consistent core. Use these parts as your baseline QA test case template fields:

FieldPurpose
IDStable reference for reports and traceability
TitleOne-line statement of the behavior under test
PriorityRelative importance (for example High / Medium / Low)
TypePositive, negative, or edge
PreconditionsState that must already be true
Test dataAccounts, inputs, flags, or fixtures needed
StepsOrdered actions a tester can follow
Expected resultObservable outcome if the product is correct
Actual resultFilled during execution
StatusPass / Fail / Blocked / Not run
NotesEnvironment quirks, evidence links, or follow-ups

Optional fields such as module, story ID, or automation candidate can help, but only add them if your team will keep them current.

How to write a QA test case step by step

1. Start from the behavior, not the UI chrome

Begin with the requirement or acceptance criterion. Ask what the user should be able to do, under which conditions, and what proves success. UI labels change; the behavior is what you are protecting.

If you are converting a user story to test cases, extract the goal, actors, preconditions, and acceptance criteria first. Draft cases from those facts instead of inventing steps from a mockup alone.

2. Write a specific title

Weak: “Login test.”
Strong: “Valid user signs in with email and password and reaches dashboard.”

A strong title makes suite reviews faster and helps people find the right case later.

3. Define preconditions tightly

Preconditions answer “what must already be true?” Examples: the account exists and is active, the tester is logged out, stale auth cookies are cleared, and any required feature flag is enabled. Put shared environment setup in a short suite note; keep case-level preconditions local.

4. Specify test data explicitly

Name the account, password pattern, or input values. For sensitive credentials, reference a named test account rather than pasting production secrets into the case.

5. Keep steps atomic and observable

Each step should be one action or one tightly related group:

  1. Open /sign-in
  2. Enter email active.user@example.com
  3. Enter password CorrectHorse-Battery1
  4. Select Sign in

Avoid steps like “log in as a normal user and verify everything looks fine.”

6. Write an expected result that can fail clearly

Expected results should be observable: URL, message text, visible page region, disabled control, or created record. Avoid “system works correctly.”

7. Assign priority based on risk

High priority usually means authentication, payments, data loss, permissions, or blockers for core journeys. Priority is a planning tool, not a ranking of people’s work.

8. Review for overlap

Before adding a case, ask whether an existing case already proves the same behavior. Duplicate near-copies inflate suites without improving confidence.

A complete login test case example

Here is a realistic software test case example you can adapt. It is written for manual execution and structured enough to support later automation discussions.

Title: Valid user signs in with email and password and reaches dashboard

Priority: High

Type: Positive

Preconditions:

  • An active user account exists: active.user@example.com
  • The account is not locked and the password is known
  • Tester is logged out of the application
  • Application sign-in page is reachable

Test data:

  • Email: active.user@example.com
  • Password: CorrectHorse-Battery1

Steps:

  1. Navigate to the sign-in page.
  2. Enter the email from test data into the email field.
  3. Enter the password from test data into the password field.
  4. Select Sign in.
  5. Observe the landing page and signed-in chrome (for example account menu or dashboard heading).

Expected result:

  • User is authenticated successfully.
  • Browser navigates to the dashboard (or the product’s default signed-in home).
  • No error banner is shown.
  • A signed-in user indicator is visible.

This is the happy path. The next section adds the negative and edge coverage most login suites need.

Positive, negative, and edge-case examples

Use a small matrix around the same feature so coverage is intentional instead of improvised.

Valid login (positive)

Covered above. Keep one primary valid-login case clean. If roles land on different homes, add separate cases per role instead of branching inside one case.

Invalid password (negative)

Title: Sign-in fails with an incorrect password and shows a safe error

Preconditions: Active account exists; user is logged out

Test data: Valid email + incorrect password

Steps: Enter valid email, enter wrong password, submit

Expected result: Sign-in is rejected; user remains unauthenticated; a generic authentication error is shown without revealing whether the email exists if that is your security standard; the password can be corrected and retried according to product rules

Locked account (negative / security)

Title: Locked account cannot sign in and receives the locked-state guidance

Preconditions: Account exists and is locked (after failed attempts or admin lock)

Test data: Locked account credentials

Steps: Attempt sign-in with the locked account’s valid password

Expected result: Access is denied; user sees the locked-account message or recovery guidance defined by the product; no dashboard access is granted

Empty required fields (negative / validation)

Title: Sign-in blocks submit when email or password is empty

Preconditions: User is on the sign-in page and logged out

Test data: Empty email, empty password, and one-field-empty combinations

Steps:

  1. Leave both fields empty and attempt submit.
  2. Enter email only and attempt submit.
  3. Enter password only and attempt submit.

Expected result: Validation prevents authentication; required-field messaging appears; user remains on sign-in

Session behavior (edge)

Title: Authenticated session persists within the allowed window and expires as designed

Preconditions: Valid login completed; session rules for the environment are known (idle timeout, absolute timeout, refresh behavior)

Steps:

  1. Complete valid login.
  2. Navigate within the app to confirm authenticated access.
  3. Wait for the configured timeout, or simulate expiry if your harness supports it.
  4. Attempt to open a protected page.

Expected result: While the session is valid, protected pages load. After expiry, the user must sign in again and cannot use the stale session for protected content.

These five cases communicate far more than a single “test login” note. Expand only for product-specific rules such as SSO, MFA, or passwordless links.

Common test case writing mistakes

Vague titles and expected results

“Verify login works” does not tell a tester what success looks like. Replace vague verbs with observable outcomes.

Steps that hide setup

If a step says “create the necessary data,” the case is incomplete. Make data creation explicit or list the fixture.

Multiple behaviors in one case

If one case validates login, profile load, and notification badges, a single failure becomes hard to diagnose. Split by behavior.

UI-coupled wording that rots quickly

Prefer stable intents (“select Sign in”) over brittle pixel-level directions unless layout risk is the point of the case.

No negative coverage

Happy-path-only suites miss the defects users feel most: validation gaps, lockouts, and confusing errors.

Copy-paste duplication

Twenty near-identical cases with one field changed are hard to maintain. Keep one representative case, or parameterize when your process allows it.

Writing for the author instead of the next reader

If only you can run the case, it is a personal note, not a team artifact.

Test case writing best practices

These test case writing best practices keep suites readable as the product grows:

  1. One primary behavior per case. Branching belongs in separate cases.
  2. Make expected results falsifiable. Another person should know when to fail the case.
  3. Prefer stable domain language. Use clear product terms from the story.
  4. Keep data realistic but safe. Use synthetic accounts and non-production secrets.
  5. Trace cases to stories or acceptance criteria when your workflow needs auditability.
  6. Review high-risk cases the way you review high-risk code changes.
  7. Retire or rewrite stale cases when rules change. A wrong case is worse than a missing one.
  8. Balance depth with maintainability. More cases are not automatically more confidence.
  9. Separate exploratory charters from scripted cases. Both are valuable; mixing them confuses reports.
  10. Write for skimming. Titles and expected results should carry meaning during suite review.

When you are deciding how deep a suite should go for a story, compare approaches in Choosing Basic, Standard, or Deep coverage.

A reusable QA test case template

Copy this Markdown table into tickets, docs, or your test management tool and fill one row per case. This QA test case template is intentionally compact so teams will actually use it.

FieldExample entry
IDAUTH-001
TitleValid user signs in with email and password and reaches dashboard
PriorityHigh
TypePositive
Module / StoryAuthentication / PROJ-123
PreconditionsActive user exists; tester logged out; /sign-in reachable
Test dataactive.user@example.com / approved test password
Steps1) Open sign-in 2) Enter email 3) Enter password 4) Select Sign in 5) Observe destination
Expected resultUser reaches dashboard; signed-in indicator visible; no auth error
Actual result(execution)
Status(Pass / Fail / Blocked)
NotesInclude environment name and evidence links

Keep a short companion list of shared suite preconditions (browser, base URL, feature flags) so individual cases stay focused.

When to use Basic, Standard, or Deep coverage

Not every story needs the same number of manual testing test cases. Match depth to risk.

Basic

Use for low-risk changes when a short happy-path set is enough. Example: a copy change on an authenticated settings label that does not alter validation.

Standard

Use for typical feature work: primary flow plus a few meaningful negatives. Example: a new required field with validation and one permission check.

Deep

Use for authentication, billing, permissions, migrations, or anything with high blast radius. Example: login, lockout, session expiry, and recovery together.

For a fuller decision framework, read Choosing Basic, Standard, or Deep coverage. For story intake into case design, see From Jira story to structured QA workflow. Plan differences that affect generation depth are on Pricing, and setup references live in Docs.

How AI can assist without replacing QA review

AI can speed up first drafts when acceptance criteria are already clear. It is often useful for turning a story into candidate cases, suggesting negative and edge angles, reformatting rough notes into a consistent template, and drafting BDD-style scenarios from structured cases.

AI should not be the final authority on risk, product nuance, or release readiness. Humans still confirm alignment with acceptance criteria, remove duplicates and implausible steps, adjust for environment and data limits, and decide what is worth executing in this release.

Treat generated output as an accelerated draft. The review is still QA work.

Final checklist

Before you mark a case or suite ready for execution:

  • Title states a single, testable behavior
  • Preconditions are complete and not assumed
  • Test data is explicit and safe to share
  • Steps are ordered, atomic, and free of hidden setup
  • Expected result is observable and unambiguous
  • Priority reflects user or business risk
  • Positive, negative, and relevant edge paths are considered
  • Case does not duplicate an existing case without reason
  • Story or requirement traceability is recorded if required
  • A second person could run the case without asking you for context

If you can check those boxes, you are producing a maintainable QA asset—not just filling a form.

Generate structured cases from your stories

When you want a faster first draft from Jira stories and acceptance criteria, QA Workflow Assistant can convert those inputs into structured test cases, edge cases, negative scenarios, and BDD-oriented output you can review before export or Jira/Xray push. Use it to accelerate drafting, then apply the same checklist above so ownership stays with your QA team.