How to Write Test Cases in Software Testing: An AU Guide

How to Write Test Cases in Software Testing: An AU Guide

21 min read
software testingtest case writingqa automatione2e testingagile development

It’s late, the release already went out, and a message lands in Slack that nobody wants to see. Checkout is broken. Login works for some users and fails for others. A billing rule changed, but the regression suite stayed green because the test only checked that a button was visible, not that the payment succeeded.

That’s the problem with bad test cases. They create false confidence.

A lot of teams think they have a tooling problem. Sometimes they do. But more often, they have a test design problem first. The script is brittle because the scenario was vague. The assertions are weak because the expected outcome was never written clearly. The suite is huge, but it still misses the bugs that matter.

If you want to learn how to write test cases in software testing, start there. A strong test case isn’t admin overhead. It’s the shortest path to fewer escaped defects, faster releases, and less time wasted babysitting Playwright or Cypress runs that should have caught the issue the first time.

Why Great Test Cases Are Your Best Defence Against Bugs

Teams often don’t feel the cost of weak test cases when they write them. They feel it later, usually under pressure.

A rushed release goes live. A core flow breaks. Support logs the issue, engineering scrambles, and the team starts reading through tests that technically passed but never validated the underlying business rule. The suite said “green”. Customers experienced “broken”.

That’s common in fast-moving Australian SaaS teams. In Australia, 68% of startups report test flakiness as a top barrier to fast shipping, according to the 2025 Standish Group CHAOS Report AU edition referenced here. When your tests are flaky, people stop trusting them. When they stop trusting them, they ignore failures. After that, the suite becomes noise.

What a good test case actually does

A proper test case does more than tell a tester what to click.

It captures intent. It tells the team what must be true before the test starts, what behaviour matters, what data the scenario depends on, and what result would count as success or failure. That makes it useful to more than QA.

Product managers use it to confirm requirements. Developers use it to spot gaps before they code. DevOps engineers use it to decide what should block a deployment.

Practical rule: If a test case can pass while the user still can’t complete the task, the test case is weak.

Why small teams get hit hardest

Big organisations can sometimes absorb poor quality for a while. Small teams can’t.

A startup shipping every week doesn’t have spare time for long triage meetings about whether the failure is in the app, the environment, or the test script. If your suite is fragile, every change gets more expensive. The team moves slower, not because they lack automation, but because their automation doesn’t represent real user risk.

That’s why test case writing matters as a business practice, not just a QA activity.

  • Clear cases reduce ambiguity: developers know what to build and what conditions matter.
  • Traceable cases reduce blind spots: teams can map coverage back to stories and releases.
  • Maintainable cases reduce wasted effort: fewer rewrites after UI shifts or workflow tweaks.
  • Better cases improve release confidence: failing tests mean something, and passing tests mean something too.

A brittle script is often just a badly written test case in code form. Fix the thinking first. The tooling gets easier after that.

The Anatomy of a High-Quality Test Case

Bad test cases usually fail in predictable ways. The title is vague. Preconditions are missing. Steps bundle three ideas into one. Expected results say “works as expected”, which means nothing. Then someone automates it and wonders why the script is unreliable.

That’s exactly why structure matters. Poor coverage in automated scripts is a major issue. 62% of defects in automated scripts originate from inadequate test coverage, and standards like IEEE 829 matter because they require fields such as unique IDs and pre/post-conditions for traceability and quality, as noted in this GeeksforGeeks reference on test cases.

The fields you actually need

You don’t need bloated paperwork. You need enough structure that another person can run the case, understand it, and trust the result.

Field Purpose Example
Test Case ID Gives the test a unique reference for traceability AUTH-LOGIN-001
Title States the single behaviour under test Standard user logs in with valid credentials
Requirement or user story Links the case to a business need US-14 User authentication
Preconditions Defines the required starting state User account exists and is active
Test data Specifies the exact inputs valid email, valid password
Steps Lists atomic actions in order Open login page, enter email, enter password, click Sign in
Expected result Defines the measurable outcome User lands on dashboard and sees account name
Postconditions States the expected end state if relevant Active session created
Actual result Records what happened during execution User redirected to dashboard
Status Captures pass, fail, or blocked Pass
Notes Adds clarifications or defect references Fails only on Safari in staging

Why each field matters

The ID looks administrative until you need to trace a failed deployment back to a missed requirement.

The preconditions stop a lot of nonsense. If the test assumes an active user, a seeded cart, or a browser state but never says so, you get inconsistent execution and pointless failures.

The steps should be atomic. “Log in and check billing” is not a step. That’s two separate actions and at least two possible failure points.

The expected result is where many teams get lazy. “User can log in” isn’t strong enough. Better is something specific and observable: the user reaches the dashboard, a session is created, and an error message does not appear.

A test case should describe one intent clearly enough that another tester, developer, or AI agent won’t need to guess what success means.

A weak example versus a usable one

Weak version:

  • Title: Test login
  • Steps: Enter details and log in
  • Expected result: Login works

Usable version:

  • Title: Standard user logs in with valid credentials
  • Preconditions: User account exists, account is active, user is logged out
  • Test data: [email protected] / valid password
  • Steps:
    1. Open the login page
    2. Enter the registered email address
    3. Enter the valid password
    4. Click Sign in
  • Expected result:
    1. User is redirected to the dashboard
    2. User’s name is visible in the top navigation
    3. No authentication error message is shown

That level of clarity makes automation easier because the logic is already sound.

If your team wants a reusable layout, this test case template from e2eAgent.io is a practical starting point. The format matters less than the discipline behind it.

Your Step-by-Step Process for Writing Test Cases

Most bad test cases start too late and too shallow. Someone waits until the feature is built, skims the UI, and writes a couple of checks based on what they see. That catches obvious breakage, but it misses assumptions, permissions, error states, and workflow edges.

In Australian teams, timing matters. Writing 45% of test cases before development can save up to 30% in costs, according to the 2024 AU TestDevLab survey summarised here. If you write after the build, you’re already reacting. If you write before and during, you’re shaping quality.

Start with requirements, not screens

A screen is only the visible surface of a workflow.

Before writing a test case, read the user story, acceptance criteria, design notes, and any rules sitting in a ticket comment that everyone is pretending not to rely on. Ask questions early.

For a login form, that means checking things like:

  • Account state: Can suspended users attempt login?
  • Validation rules: What counts as an invalid email or password format?
  • Session behaviour: Where does the user land after login?
  • Permissions: Do different roles see different post-login states?
  • Error handling: What message appears after a failed attempt?

If those answers aren’t clear, the test case shouldn’t be guessed into existence. Get the answer first.

A person writing notes in a notebook next to a laptop displaying a software testing flowchart.

Write the happy path first

The first case should prove the main user goal works.

Take a simple login feature. Your base case might be:

  • Standard user with valid credentials logs in successfully
  • User reaches dashboard
  • Session is created
  • No error message appears

That’s your anchor. If you can’t write that clearly, you’re not ready to automate anything.

Then write the failure paths people actually hit

Most escaped bugs hide outside the ideal path.

For the same login feature, write separate cases for:

  1. Invalid password The user enters a correct email and wrong password. The system should reject access and show the correct error state.

  2. Unregistered email Useful for checking whether the product leaks account existence or handles unknown users cleanly.

  3. Empty required fields This catches client-side validation gaps and broken form rules.

  4. Locked or suspended account A common source of production confusion because teams often validate login mechanics but not account lifecycle rules.

  5. Session edge conditions If the user is already logged in, what happens when they revisit the login URL?

Each of these deserves its own case. Don’t cram them into one “test login validations” script.

Use concrete test data

Vague data creates vague results.

Don’t write “enter valid user details”. Write the exact type of user and the exact input condition. If the value matters, name it. If the account state matters, state it. If the browser must start logged out, include that in the preconditions.

A test case becomes maintainable when the next person can run it without asking what you meant.

Keep steps atomic

One step should contain one action.

Bad:

  • Enter valid details and verify dashboard opens

Better:

  • Enter registered email address
  • Enter valid password
  • Click Sign in
  • Verify dashboard is displayed

Atomic steps help humans during manual execution and help automation when something fails. If one bundled step breaks, the team wastes time figuring out which part failed.

Don’t write for the tester who already knows the feature. Write for the person who didn’t attend the refinement meeting.

Make expected results observable

“Should work” is useless.

An expected result must be something a tester, a script, or an AI agent can observe. That might include:

Weak expected result Strong expected result
User logs in User is redirected to the dashboard
Error shown “Invalid email or password” message is displayed below the form
Data saved New address appears in the saved addresses list
Upgrade blocked Upgrade modal appears and premium page content remains hidden

Cover boundary and negative thinking

Even simple features need edge coverage.

For forms, think about invalid input, empty fields, overlong values, formatting errors, interrupted flows, duplicate submissions, stale state, and permissions. That mindset is what separates a test suite that looks busy from one that prevents defects.

Review before you automate

A lot of teams automate too soon. They convert weak manual cases into expensive weak scripts.

Before a case becomes Playwright, Cypress, or a plain-English AI scenario, review it for:

  • one clear objective
  • explicit preconditions
  • exact data
  • atomic steps
  • observable expected results
  • traceability to a requirement
  • value to the release

If it fails that review, rewriting the code won’t fix the problem. The test design is still wrong.

From Manual Scripts to AI-Ready English Scenarios

Traditional test cases were built for humans to execute and developers to automate line by line. That still has value. But many teams now have a maintenance problem, not just a coverage problem.

The old pattern is familiar. QA writes detailed steps. Automation converts them into selectors and assertions. The UI shifts, the DOM changes, half the suite fails, and everyone argues about whether the failures are “real”. The business logic may still be fine. The test has become the unstable part.

A conceptual graphic illustrating AI test evolution with digital interfaces, robotic hands, and a paper checklist.

The shift from step scripts to scenario thinking

A rigid manual script often looks like this:

  • Go to /login
  • Click input with selector X
  • Type email
  • Click input with selector Y
  • Type password
  • Click button with selector Z
  • Assert element .dashboard-title is visible

That’s executable, but it’s tightly coupled to implementation.

A stronger scenario describes user intent and business outcome instead:

  • A standard user logs in with valid credentials and reaches the dashboard
  • A user with an invalid password is denied access and sees the correct error message
  • A user without premium access opens a premium feature and sees an upgrade modal instead of the feature content

The second format is better because it survives UI changes more easily. It also lets people outside engineering contribute.

What plain-English scenarios need to include

Writing in English doesn’t mean writing loosely.

An AI-ready scenario still needs the same essentials as a strong classic test case:

  • User context: who is performing the action
  • Starting state: what must already be true
  • Action: what the user tries to do
  • Outcome: what should happen
  • Boundaries: what should not happen

For example:

Poor plain-English scenario Better plain-English scenario
Test login Logged-out standard user signs in with valid credentials and lands on the dashboard with their account name visible
Test payment failure User submits an expired card at checkout and sees a payment failure message while the order remains unconfirmed
Test upgrade gating User on a standard subscription opens a premium report and sees an upgrade modal, with report data remaining inaccessible

Where this helps most

This style works well when product, QA, and engineering need a shared testing language.

Startup founders and product managers usually know the business rules. They often don’t know Playwright syntax, and they shouldn’t need to. If they can describe a risk clearly, they can contribute useful test coverage.

That’s why natural-language workflows are getting attention. For teams exploring this approach, QA via natural language is the core shift in mindset. You’re no longer treating test creation as script authoring first. You’re treating it as scenario definition first.

One option in that category is e2eAgent.io, which lets teams describe a test scenario in plain English and have an AI agent execute it in a real browser. That’s useful when the team wants broader participation in test creation without hand-writing every automation script.

What not to do with AI-generated or AI-executed tests

AI doesn’t rescue a sloppy scenario.

If the prompt says “check checkout works”, the output will still be weak because the underlying requirement is weak. You still need precision.

Avoid these mistakes:

  • Vague actors: “user” is too broad if roles change permissions
  • Missing state: logged in, logged out, trial, premium, suspended, seeded cart
  • No observable result: “works correctly” can’t be verified reliably
  • Bundled intent: login, search, checkout, and logout in one scenario is still bad test design

A better AI-ready case is short, specific, and outcome-based.

Here’s a useful reference point before you define scenarios for automation:

The real trade-off

Traditional scripts give you very explicit control. They also demand more upkeep when interfaces change.

Plain-English scenarios reduce maintenance overhead and widen who can contribute, but only if the team keeps discipline around clarity, scope, and expected results. If they don’t, they just move ambiguity from code into prose.

The useful middle ground is simple. Keep the rigour of classic test design. Drop the unnecessary fragility of over-specified manual scripts.

Common Test Case Pitfalls and a Review Checklist

Weak test cases usually don’t fail because the team lacks effort. They fail because the suite fills up with low-value checks that look organised but don’t detect meaningful risk.

In Australian QA benchmarks, common pitfalls like vague steps and happy-path bias cause 70% of test failures to miss production bugs. The same analysis says Test Case Effectiveness should target more than 25%, and AU teams that reach that level report 40% higher defect detection rates, according to this TestMu AI analysis.

A professional checklist infographic showing six common pitfalls to avoid when writing software test cases.

The mistakes that keep showing up

Some patterns are almost always a bad sign:

  • Happy-path only: the case proves the ideal flow and ignores invalid inputs, permission failures, and interrupted states.
  • Vague language: “click button”, “submit form”, and “verify success” force the executor to interpret what you meant.
  • Bundled scenarios: one test tries to cover login, profile update, checkout, and email confirmation in a single chain.
  • Missing preconditions: nobody knows whether the user must already exist, the cart must be seeded, or the browser must start logged out.
  • UI obsession: the test checks labels and buttons but ignores whether the backend state or business rule changed correctly.
  • Stale coverage: the feature changed, but the case still reflects an old workflow.

If a test case has to be explained verbally before someone can execute it properly, it isn’t finished.

A practical review checklist

Use this in peer review before the case enters a suite.

  • Single purpose: Does the case validate one behaviour only?
  • Clear actor: Does it identify the right user role or account state?
  • Defined preconditions: Is the starting state explicit?
  • Exact data: Are test inputs specific rather than implied?
  • Atomic steps: Can each action fail independently and be diagnosed quickly?
  • Observable outcome: Could another person tell clearly whether it passed or failed?
  • Negative thinking: Have you covered likely failure paths separately?
  • Requirement link: Can the team trace this case back to a story, rule, or acceptance criterion?
  • Maintenance value: If this case fails in CI, will anyone care enough to fix it immediately?

One metric that matters

Test Case Effectiveness is calculated as (Defects Detected / Test Cases Run) × 100. Don’t treat it as a vanity metric. It’s a signal.

If the suite is large and that effectiveness is low, the team is likely writing too many redundant or shallow cases. Fewer, sharper tests often produce better results than a bloated suite full of recycled happy paths.

Integrating Test Cases into Your CI/CD Pipeline

A test case sitting in a document helps nobody during a deployment. It becomes valuable when it feeds a release decision.

That’s where structure pays off. Clean test cases turn into reliable suites. Reliable suites give CI meaningful feedback. Without that chain, the pipeline is just running automation for its own sake.

Organise suites by release risk

Not every test belongs in every pipeline stage.

The fastest pipelines separate cases by purpose:

  • Smoke suite: confirms the build is testable and the core flows are alive
  • Sanity suite: checks the changed area behaves as expected
  • Regression suite: protects broader behaviour across the product
  • Targeted risk suite: focuses on the feature area with the highest release risk

The important point isn’t the label. It’s the decision logic behind it.

A conceptual digital representation of data pipeline flow moving through high-tech server racks in a data center.

Prioritise by impact, not by habit

Risk-based sequencing works better than alphabetical sequencing, historical accident, or “whatever we automated first”.

In AU CI pipelines, using a risk-based methodology yields 92% pass rates and a 35% defect detection uplift, while top-quartile QA leads improve outcomes further by focusing on negative tests, which cuts change failure rates by 22% in SaaS pipelines, based on Testlio-linked AU metrics.

That means the high-impact tests should run first. Payment. Authentication. Permissions. Data creation. Critical integrations. Not the cosmetic checks that happen to be easy to automate.

What good pipeline-ready cases have in common

Pipeline-friendly tests are:

Trait Why it matters in CI
Independent One failure doesn’t cascade into five false failures
Deterministic The same input produces the same expected result
Fast to diagnose The failure points to a clear business rule or state
Stable on setup Test data and preconditions are explicit
Relevant A failing result should influence a release decision

That’s also why negative cases belong in CI. If your pipeline only proves the app works under ideal conditions, it won’t protect the release when users do something messy.

Handle failures like product signals

A failed test should answer three questions quickly:

  1. What behaviour broke?
  2. Under what conditions did it break?
  3. Should this block release?

If the case was written well, those answers are already in the title, preconditions, and expected result. If the case was vague, triage becomes a detective exercise.

Teams trying to tighten this feedback loop should think beyond raw automation count. This practical guide on how to reduce QA testing time in CI/CD is relevant because speed only helps when the output is trustworthy.

A fast pipeline with weak tests ships bugs faster. A disciplined pipeline with sharp tests ships confidence.

Frequently Asked Questions About Test Case Writing

What’s the difference between a test case, a test scenario, and a user story

A user story describes a business need from the user’s perspective.

A test scenario is broader. It states what should be tested, such as “premium users can access reports” or “invalid login attempts are rejected”.

A test case is the executable version. It defines the preconditions, steps, data, and expected outcome for one specific validation.

How many test cases are enough for one feature

There isn’t a fixed number that makes sense across all features.

A simple feature may need only a handful of cases. A risky workflow may need many more. The right question is whether you’ve covered the primary path, key negative paths, permissions, business rules, and the most likely failure conditions. Stop counting cases and start checking risk.

Should product managers or founders write test cases

They can absolutely contribute, especially at the scenario level.

Non-technical team members often know the business logic, edge conditions, and customer pain points better than anyone. They shouldn’t be forced to write automation code. But they can and should help define scenarios, expected outcomes, and risky behaviours worth validating.

Are detailed manual test cases still useful if we automate

Yes, if the detail serves clarity rather than bureaucracy.

A well-written manual case often becomes the basis for automation. What you want to avoid is duplicating useless detail. Don’t preserve every click path if the core value is the business rule and the expected result.

When should I write test cases

As early as the requirement is stable enough to discuss behaviour clearly.

Writing after development starts is sometimes unavoidable, but writing earlier exposes ambiguity before it becomes a defect. Even a draft scenario during refinement is useful if it forces the team to define what success looks like.

What makes a test case brittle

Usually one of four things:

  • it depends too heavily on unstable UI details
  • it combines multiple behaviours
  • it lacks clear preconditions
  • it asserts the wrong thing

Brittleness often looks like a tooling failure, but the root cause is usually weak test design.


If your team is tired of maintaining brittle browser tests, e2eAgent.io offers a different approach. You describe the scenario in plain English, and the AI agent executes it in a real browser and verifies outcomes. For fast-moving product teams, that can make it easier to turn clear test thinking into automated coverage without hand-maintaining every Playwright or Cypress script.