Skip to content

Learn

How to write test cases: A step-by-step guide

Learn how to write effective software test cases with step-by-step guidance, templates, examples, and techniques that improve software quality.

write a test case

TL;DR

  • A test case documents the preconditions, test data, actions, and expected results used to verify a specific software behavior or requirement.
  • Effective test cases cover positive and negative scenarios, edge cases, boundary conditions, permissions, and data variations.
  • Clear, atomic steps and measurable expected results make tests easier to execute, review, automate, and maintain as software changes.
  • Test cases improve coverage, traceability, defect detection, and collaboration across development and QA teams.
  • Agentic AI can accelerate test case creation and identify coverage gaps, while human testers remain responsible for reviewing scenarios, expected results, and risk.

Learning how to write test cases is one of the most practical skills a tester, developer, or QA lead can develop. A well-written test case turns vague ideas about quality into concrete checks that can be repeated, reviewed, and automated.

It describes what should happen when a user, system, or external service interacts with the application under defined conditions.

Rather than write the longest test case or the most detailed one, the goal is to write a test case that is clear enough for someone else to run without asking questions, specific enough to measure pass or fail, and maintainable enough to evolve with the software.

I saw the value of clear test cases when fixing a performance issue in a latency-sensitive system. I started by establishing a baseline so I could measure whether each change improved or degraded performance.

The test cases helped me track latency and throughput as I adjusted the system ahead of a major marketing campaign. That made it possible to add only the servers we needed, instead of over-provisioning out of uncertainty.

The same approach helped when using test-driven development for new features or bug fixes. I would write a failing test that represented the bug, then write the code to make that test pass. That gave me confidence in the fix before moving to upper environments.

A good test case describes what the software should do, not how the code happens to implement it.

What are software test cases?

A test case outlines the setup, inputs, running steps, and expected results needed to confirm that a system behaves correctly under a specific condition.

It serves as a repeatable contract between the requirement and the software’s actual behavior, making it clear whether a feature works as intended. It describes what should happen when a user, system, or external service interacts with the application under defined conditions.

A test case should be clear enough that someone who did not write the code can understand what is being tested and how to tell if it passed or failed.

It should cover normal usage, but also edge cases, negative scenarios, and conditions that could cause the software to behave unexpectedly.

A good test case does not explain how the code works internally. It explains what the software should do from the perspective of the user or the requirement. A test case describes behavior, not implementation.

A test case should be clear enough that someone who did not write the code can understand what is being tested and how to tell if it passed or failed.

Why does learning how to write test cases matter?

Learning how to write test cases matters because it turns vague ideas about quality into concrete checks that can be repeated, reviewed, and automated. When test cases are clear, teams can catch defects earlier, reduce rework, and build confidence before releasing changes.

Writing test cases is not just about proving that a feature works under ideal circumstances. In The Art of Software Testing, Glenford Myers noted that “testing is the process of executing a program with the intent of finding errors.”

When you approach test writing with that mindset, you design cases that actively challenge assumptions, surface defects early, and protect downstream environments.

Clear test cases also help new team members understand the system faster. They provide a shared language between developers, testers, product owners, and operations. When a requirement changes, well-written test cases make it easier to see what needs to be updated and what still applies.

I saw this firsthand when fixing a performance issue in a latency-sensitive system. I started by establishing a baseline so I could measure whether each change improved or degraded performance.

The test cases helped me track latency and throughput as I adjusted the system ahead of a major marketing campaign. That made it possible to add only the servers we needed, instead of over-provisioning out of uncertainty.

Test cases turn uncertainty into measurable feedback. The same approach helped when using test-driven development for new features or bug fixes.

I would write a failing test that represented the bug, then write the code to make that test pass. That gave me confidence in the fix before moving to upper environments.

Test case vs. test scenario vs. test script

These terms are often used interchangeably, but they describe different levels of detail.

A test scenario is a high-level description of what to test

It outlines the functionality or user flow without specifying exact steps or data. For example, “verify that a user can log in with valid credentials” is a scenario.

A test case is a detailed, executable check with preconditions, steps, data, and expected results

It takes a scenario and makes it specific enough to run and evaluate. For example, “log in with testuser@example.com and password Test@123, verify the user is redirected to the dashboard within 2 seconds” is a test case.

A test script is an automated version of a test case, usually written in code

Test scripts perform the same steps and check the same results, but it is executed by a tool or framework instead of a person.

Here’s a table to help you keep the concepts in mind.

ConceptPurposeLevel of detailExample
Test scenarioDefines what to test at a high levelLow (broad user action or feature)Verify user can log in with valid credentials
Test caseDefines how to test with exact steps and dataHigh (preconditions, steps, expected results)Navigate to “/login”, enter “testuser@example.com”, click submit, verify dashboard loads
Test scriptAutomates the execution of a test case in codeTechnical (executable code and programmatic assertions)“await page.goto(‘login’); await page.fill(‘#email’, ‘testuser@example.com’);”

 

A simple way to think about it is this. A scenario describes what to test. A test case describes how to test it. A test script automates that test case.

How to write test cases step by step

Writing test cases becomes easier when you follow a consistent process. The steps below work for manual and automated tests, and they fit both agile and traditional workflows.

how-to-generate-test-case

1. Understand the requirement or user story

Read the requirement, user story, or acceptance criteria carefully. Identify what behavior needs to be verified and what conditions could cause it to fail.

If the requirement is unclear, ask for clarification before writing the test. A test case should trace back to a clear requirement or acceptance criterion.

2. Identify the test scenarios

Break the requirement into smaller, testable scenarios. Include positive flows, negative flows, boundary conditions, permission differences, and data variations. Think about what could go wrong, not just what should go right.

For example, a login feature might need scenarios for valid credentials, invalid credentials, locked accounts, missing fields, and session timeouts.

Another tester should be able to run the test without guessing what needs to be in place first.

3. Define preconditions and test data

List the conditions that must be true before the test can run. This might include environment setup, user accounts, feature flags, or database state.

Prepare the test data you will use, such as usernames, passwords, or input values. Clear preconditions make the test repeatable. Another tester should be able to run the test without guessing what needs to be in place first.

4. Write the test steps

Write numbered steps that describe the actions to perform. Each step should be a single, observable action. Use action verbs like “navigate,” “enter,” “click,” “submit,” or “verify.” Avoid combining multiple actions into one step. If a step fails, it should be easy to see which action caused the problem.

5. Define the expected results

For each step, describe the expected outcome. The expected result should be specific and measurable. Instead of “the user logs in successfully,” write “the user is redirected to the dashboard and the welcome message displays their name.” Expected results define what pass means.

6. Add postconditions if needed

Some tests need cleanup or verification after the main steps. Postconditions describe the state of the system after the test runs. For example, “the user session is terminated” or “the order appears in the database with status PAID.”

7. Assign a test case ID and metadata

Give the test case a unique identifier, such as TC-LOGIN-001. Add metadata like the module or feature, priority, related requirement, and automation status. This helps with traceability and maintenance.

8. Review the test case

Have another tester, developer, or product owner review the test case. Check for clarity, completeness, and alignment with the requirement. Update any steps that are ambiguous or missing. A test case is not finished until someone else can run it without asking questions.

A test case is a living artifact that should evolve with the software.

Execute and update

Run the test case and record the actual results. If the test fails, determine whether the software has a defect, the test is outdated, or the expected behavior changed. Update the test case as needed to keep it accurate. A test case is a living artifact that should evolve with the software.

Once you have a clear process in place, the next step is to make sure each test case contains the right details to stay useful over time.

Essential elements of an effective test case

An effective test case includes a small set of core fields that make it repeatable and easy to review. The exact format may vary by team, but the essential elements remain the same.

A test case needs a unique ID, clear description, preconditions, test steps, test data, expected results, and a way to track pass or fail status.

The unique ID helps with traceability and maintenance. The description explains what the test verifies. Preconditions define the state the system must be in before the test runs. Test steps describe the actions to perform.

Test data provides the specific inputs. Expected results define what pass means. Status tracks whether the test passed, failed, or was blocked.

Optional but useful fields include priority, related requirement or user story, automation status, environment details, and comments.

These help teams prioritize work, understand coverage, and maintain the test suite over time. A test case should be atomic, meaning it tests one scenario or behavior at a time.

Test case template with a worked example

A simple template makes it easier to write consistent test cases across the team. The example below shows how the template works in practice.

test-case-log-in

This same template can be adapted for negative scenarios, edge cases, or API tests. For example, a negative test case might use invalid credentials and expect an error message instead of a successful login.

Best practices for writing maintainable test cases

Maintainable test cases reduce the effort needed to keep the test suite current as the software evolves. The following practices help teams write tests that stay useful over time.

  1. Write test cases that are clear enough for someone else to run without asking questions.
  2. Keep steps atomic and specific. Each step should describe one action. Use action verbs like “navigate,” “enter,” “click,” or “verify.” Avoid combining multiple actions into a single step.
  3. Define expected results that are specific and measurable. Instead of “the system works correctly,” write “the user is redirected to the dashboard within 2 seconds and the welcome message displays their name.”
  4. Keep test cases independent. Each test should be able to run on its own without relying on the state left by another test. This reduces flaky results and makes debugging easier.
  5. Use consistent naming and structure across the team. That makes it easier to scan, review, and automate tests later.

Treat test cases as living artifacts. Update them when requirements change, add new tests for new behaviors, and retire tests when features are removed.

Maintainable test cases reduce the effort needed to keep the test suite current as the software evolves.

Common mistakes to avoid when writing test cases

Even experienced testers can fall into patterns that make test cases harder to use. Avoiding these common mistakes improves clarity and maintainability.

1. Vague steps and expected results

Steps like “test the login” or “check the system” do not tell the tester what to do or what to look for. Expected results like “the system works” are not measurable.

2. Combining multiple scenarios into one test case

A test case that tries to verify login, checkout, and reporting in one run becomes hard to maintain and debug. Keep each test focused on one behavior.

3. Missing preconditions or test data

If a test assumes a user exists but does not state it, another tester may not know how to set up the environment. That leads to inconsistent results.

4. Over-detailed steps that describe the UI instead of the behavior

Steps like “click the blue button in the top right corner” may break when the UI changes. Focus on the action and outcome, not the exact pixel location.

5. Not updating tests when the software changes

A test suite that is not maintained becomes a source of noise. Tests that no longer reflect the intended behavior waste time and reduce trust in the suite.

I once saw a team member comment out a group of tests because new code was causing the CI pipeline to fail. The intention was to keep moving and test the change in a live environment, but the tests were never enabled again.

The problem only became obvious when the code reached upper environments and unrelated functionality started breaking. That experience reinforced a simple lesson for me: a test that has stopped running cannot protect the system, even if the test itself is still correct.

A failing test is information. Commenting it out may remove the warning without removing the risk.

Testers, developers, and product owners collaborate to identify the most important behaviors and edge cases before development begins.

Writing test cases for agile and CI/CD workflows

Test cases in agile and CI/CD environments need to adapt quickly as requirements and code change. The goal is not to write perfect tests once, but to keep tests aligned with the current state of the software.

In agile teams, test cases often start as high-level scenarios during sprint planning, then become detailed test cases as the story is refined. Testers, developers, and product owners collaborate to identify the most important behaviors and edge cases before development begins.

In agile, test cases evolve alongside the user story, not after it is complete. CI/CD pipelines rely on automated tests to provide fast feedback on every change. Test cases designed for CI/CD should be independent, repeatable, and fast to execute.

They should also be easy to update when the workflow or data changes. Teams should expect test cases to change frequently in these environments. That is not a sign of poor planning. It is a sign that the tests are keeping pace with the software.

Test cases should adapt as requirements, code, and environments change.

How agentic AI can improve test case creation and maintenance

Agentic AI can help teams create and maintain test cases faster, but it should not replace human judgment. The best use of AI is to handle repetitive work while humans focus on the logic, scenarios, and risk assessment.

Agentic AI can generate boilerplate test structures, but humans should own the scenarios and expected results.

Tricentis Agentic Test Creation, for example, can analyze requirements and generate detailed test cases with preconditions, steps, and expected results.

The agent understands the context from attachments, conversation history, and the existing test library, then creates test cases that match the team’s standards.

This approach reduces manual effort and helps teams maintain consistency across test cases. It also helps identify coverage gaps by suggesting tests for edge cases or negative scenarios that might be overlooked.

The key is to treat AI as a smart new joiner to the team. It can learn fast and handle routine tasks, but it still needs guidance and review.

Humans should approve AI-generated tests, ensure they reflect real risks, and update them as the software evolves. AI should assist with test creation, not make decisions about what matters without human oversight.

Use case: scaling test creation with agentic AI

You can see how this works in practice with LTM, a financial services provider that needed to scale up their testing workflows.

Problem

Manual test design and spreadsheet uploads were slowing their delivery cycles down, making it hard to maintain consistent coverage across complex UI and API workflows.

Solution

They brought in agentic AI to help bridge the gap. Instead of building every test case by hand, testers described what they needed using plain English prompts.

The agentic system translated those requirements into structured test cases, complete with preconditions, steps, and expected results, and pushed them directly into Tricentis qTest.

Outcome

The impact was immediate. The team cut test design time in half, accelerated test automation by 67%, and achieved 100% test coverage across their core platform layers without getting buried in administrative busywork. That’s a good example of a company using the right tool for the right job.

Read more about this use case here.

Conclusion

Looking to strengthen your team’s testing practices? Explore how Tricentis helps QA teams build more consistent, scalable test coverage with unified test management. Learn more about Tricentis qTest and how it supports test case creation, execution, and maintenance across the enterprise.

For more insights on writing test cases, read How do you write your test cases? on ShiftSync.

This post was written by David Snatch. David is a cloud architect focused on implementing secure continuous delivery pipelines using Terraform, Kubernetes, and any other awesome tech that helps customers deliver results.

Tricentis qTest

Learn more about how to scale, orchestrate, and accelerate test automation for complete visibility into your testing process.

Author:

David Snatch

Guest contributor

Date: Sep. 29, 2026

FAQ

How do you write test cases?

Start by understanding the requirement or user story, then break it into testable scenarios. Define preconditions, write clear test steps, add test data, and specify the expected result for each step. Review the test case before execution to ensure it is clear and complete.

Is writing test cases easy?

Writing basic test cases is straightforward, but writing effective test cases that cover edge cases, negative scenarios, and maintainable structures takes practice. The key is to keep each test atomic, clear, and aligned with the requirement.

What is a good test case example?

A good test case example includes a unique ID, clear title, preconditions, numbered steps, specific test data, and measurable expected results. For instance, a login test case would specify the username, password, steps to submit, and the expected redirect to the dashboard.

What is the 80 20 rule in testing?

The 80 20 rule in testing suggests that 80% of defects often come from 20% of the features or code areas. Teams should focus testing effort on the highest-risk areas that are most likely to cause problems.

What is the difference between a test case and a test scenario?

A test scenario is a high-level description of what to test, while a test case provides detailed steps, data, and expected results. A scenario might say “verify login works,” while a test case specifies the exact credentials, steps, and expected outcome.

How many test cases should I write for a feature?

The number depends on the complexity and risk of the feature. Start with positive and negative scenarios, then add edge cases, boundary conditions, and permission variations. The goal is coverage, not a specific number.

Should test cases be automated?

Test cases that are repetitive, stable, and critical should be automated. Exploratory testing, one-time checks, or rapidly changing features may remain manual. The decision depends on the value and frequency of execution.

You may also be interested in...