Writing Effective Test Cases

You now know four techniques for figuring out what to test — Equivalence Partitioning, Boundary Value Analysis, Decision Tables, and State Transition Testing. But knowing what to test in your head isn't the same as documenting it in a way that anyone on the team — a teammate, your future self three months from now, or a developer reproducing a bug — can follow exactly and get the same result. That's what a test case is for: a precise, repeatable, written recipe (no pun intended) for performing one specific check.

The Standard Test Case Template

Most test case formats — whether in a spreadsheet, TestRail, Zephyr, or Jira Xray — use some version of these fields:

FieldPurpose
Test Case IDA unique identifier (e.g. TC-ADD-001) so the case can be referenced from a bug report, a test plan, or a traceability matrix.
TitleA short, specific sentence describing exactly what's being verified.
PreconditionsWhat must already be true before you start — logged in, on a specific screen, existing data present.
Test StepsThe numbered, exact actions to perform, in order — specific enough that two different people would do the same thing.
Test DataThe concrete values used while executing the steps — not "a valid title," but the literal string you typed.
Expected ResultWhat should happen if the software is working correctly — written before you run the test, not after.
Actual ResultWhat actually happened when you ran the test — filled in during execution.
StatusPass / Fail / Blocked / Not Run — the outcome, based on comparing Expected vs Actual.
PriorityHow important this specific case is to run (High/Medium/Low) — helps decide what to run first when time is short.

What Makes a Test Case Good

  • Specific. "Test adding a recipe" is not a test case, it's a topic. "Add a recipe with a title exactly 100 characters long and verify it saves" is a test case.
  • Repeatable by someone else. If a teammate who's never used RecipeBox follows your steps and test data exactly, they should land on the same result you did — no guessing about what "a recipe" or "valid data" means.
  • One clear expected result. A test case that says "should probably save, or maybe show a warning" isn't testable — a case must have exactly one unambiguous expected outcome, decided in advance.
  • Independent test data. Concrete values (an exact title string, an exact number) rather than vague placeholders, so the same steps produce the same result every time.

Worked Example 1: Add Recipe With Valid Data

Test Case IDTC-ADD-001
TitleAdd a new recipe with all fields filled in correctly and verify it saves
PreconditionsUser is logged into RecipeBox; user is on the "Add Recipe" screen
Test Steps 1. Enter the title.
2. Enter the ingredients.
3. Enter the steps.
4. Select a category from the dropdown.
5. Enter the prep time.
6. Tap "Save."
Test DataTitle: "Tomato Basil Pasta"; Ingredients: "200g pasta, 2 tomatoes, fresh basil, olive oil"; Steps: "Boil pasta. Sauté tomatoes and basil. Combine and serve."; Category: "Dinner"; Prep Time: 25
Expected ResultRecipe saves successfully; a confirmation message is shown; the new recipe ("Tomato Basil Pasta") appears in the Recipe List with category "Dinner" and prep time "25 min"
Actual Result(filled in during execution)
Status(Pass / Fail / Blocked — filled in during execution)
PriorityHigh

Worked Example 2: Prep Time Rejects an Invalid Value

Test Case IDTC-ADD-002
TitleAdd a recipe with Prep Time set to 0 and verify it is rejected
PreconditionsUser is logged into RecipeBox; user is on the "Add Recipe" screen with title, ingredients, and steps already filled in validly
Test Steps 1. Enter a valid title, ingredients, and steps.
2. Enter "0" in the Prep Time field.
3. Tap "Save."
Test DataTitle: "Iced Coffee"; Ingredients: "coffee, ice, milk"; Steps: "Combine and stir."; Prep Time: 0
Expected ResultForm is not submitted; a validation error is shown on the Prep Time field (e.g. "Prep time must be at least 1 minute"); recipe is not added to the Recipe List
Actual Result(filled in during execution)
Status(Pass / Fail / Blocked — filled in during execution)
PriorityHigh

Worked Example 3: Missing Title Blocks Submission

Test Case IDTC-ADD-003
TitleAttempt to save a recipe with the Title field left blank and verify it is blocked
PreconditionsUser is logged into RecipeBox; user is on the "Add Recipe" screen with ingredients and steps already filled in validly
Test Steps 1. Leave the Title field empty.
2. Enter valid ingredients and steps.
3. Tap "Save."
Test DataTitle: (blank); Ingredients: "flour, sugar, eggs"; Steps: "Mix and bake at 180°C for 20 minutes."
Expected ResultForm is not submitted; a validation error "Title is required" is shown; recipe is not added to the Recipe List
Actual Result(filled in during execution)
Status(Pass / Fail / Blocked — filled in during execution)
PriorityHigh

Notice how each of the three examples above traces back directly to a technique from earlier lessons: TC-ADD-001 exercises the valid equivalence partition on every field, TC-ADD-002 exercises the Prep Time boundary (0, the min-1 boundary value), and TC-ADD-003 exercises one row of the "Publish Recipe" style decision logic. Good test cases aren't invented from nothing — they come from systematically applying the design techniques you've already learned.

Common Mistakes When Writing Test Cases

  • Vague steps like "fill in the form correctly" — correctly according to whom, with what data? Spell out the literal values.
  • Missing preconditions — if the tester has to guess what state the app needs to be in first, the case isn't repeatable.
  • Multiple unrelated checks crammed into one test case — if step 3 fails, you won't know whether steps 4 and 5 would also have passed. Split unrelated checks into separate cases.
  • Writing the Expected Result after running the test. That's just describing whatever happened — it defeats the purpose of having an independent expectation to check against.
Up next: Test Scenarios vs Test Cases zooms back out — before you write ten detailed test cases like the ones above, you usually start from one higher-level scenario. This next lesson shows exactly how that breakdown works.