02 · Test Case Design & Documentation¶
A test case is the unit of work in manual testing. It is a written, repeatable instruction set that says: given this setup, do these steps, and this exact thing should happen. Written well, anyone on the team — including someone who joined yesterday — can execute it and get the same verdict you would. Written badly, it is a vague note only its author understands.
This module covers the three artefacts you will produce constantly as a tester: test scenarios, test cases, and the Requirement Traceability Matrix (RTM).
1. Scenario vs case — the difference¶
| Test scenario | Test case | |
|---|---|---|
| Level | High-level, one line | Detailed, step-by-step |
| Answers | What to test | How to test it |
| Example | "Verify login functionality" | "TC-001: Login with valid credentials" |
| Count | One scenario spawns many cases | Many per scenario |
| Written during | Early — after requirement analysis | Later — test case design phase |
Scenarios are written first, as a coverage checklist. Then each scenario is broken into positive and negative test cases.
Scenario: Verify the login functionality of the application.
Breaking it down into cases:
- TC-001 · Login with valid username and valid password (positive)
- TC-002 · Login with valid username and invalid password (negative)
- TC-003 · Login with invalid username and valid password (negative)
- TC-004 · Login with both fields empty (negative)
- TC-005 · Login with username containing leading/trailing spaces (edge)
- TC-006 · Password field masks the entered characters (UI)
- TC-007 · Account locks after 5 consecutive failed attempts (security)
- TC-008 · "Remember me" keeps the session after browser restart (functional)
Notice the ratio: one scenario, eight cases, and most of them are negative. That is normal and healthy. Beginners write only the happy path; real defects live in the unhappy ones.
2. The test case template¶
This is the standard column set. Every company tweaks it slightly, but if you can fill this in, you can adapt to any tool (Jira/Xray, TestRail, Zephyr, or a plain spreadsheet).
| Field | Purpose |
|---|---|
| Test Case ID | Unique, stable identifier — TC_LOGIN_001 |
| Module / Feature | Which area of the app |
| Test Case Title | One line describing the objective |
| Requirement ID | Links back to the requirement (feeds the RTM) |
| Priority | P1/P2/P3 — execution order when time is short |
| Type | Positive / Negative / Boundary / UI / Security |
| Preconditions | What must be true before step 1 |
| Test Data | The exact values to use |
| Steps | Numbered, atomic, unambiguous actions |
| Expected Result | Precisely what should happen |
| Actual Result | Filled in at execution time |
| Status | Pass / Fail / Blocked / Not Executed / Skipped |
| Defect ID | Bug reference if it failed |
| Executed By / Date | Audit trail |
A fully worked example¶
| Field | Value |
|---|---|
| Test Case ID | TC_LOGIN_002 |
| Module | Authentication |
| Title | Verify login is rejected with a valid username and an incorrect password |
| Requirement ID | REQ-AUTH-03 |
| Priority | P1 |
| Type | Negative |
| Preconditions | 1. Application is deployed and reachable. 2. A user account qa.user@example.com exists and is active (not locked). 3. Browser is on the /login page. |
| Test Data | Username: qa.user@example.com · Password: WrongPass123! |
| Steps | 1. Enter qa.user@example.com in the Username field.2. Enter WrongPass123! in the Password field.3. Click the Login button. |
| Expected Result | 1. User remains on /login.2. Error message "Invalid username or password." is displayed above the form in red. 3. The Password field is cleared; the Username field retains its value. 4. The failed-attempt counter for the account increments by 1. |
| Actual Result | (filled at execution) |
| Status | Not Executed |
| Defect ID | — |
Why the expected result has four numbered parts
A weak expected result says "login fails." That passes even if the app shows a raw stack trace, or silently clears both fields, or fails to increment the lockout counter. Specific expected results catch specific defects. If you cannot say precisely what should happen, the requirement is ambiguous — go ask the business analyst before writing the case.
3. Rules for writing steps that actually work¶
- One action per step. "Enter credentials and click Login" is two steps. If it fails, which half failed?
- Use exact UI labels. "Click the Submit button", not "submit the form". Quote the label as it appears on screen.
- Be data-explicit. "Enter a valid email" is not reproducible. "Enter
qa.user@example.com" is. - No assumed context. If the case needs the user logged in, that belongs in Preconditions, not implied.
- Independent cases. TC-005 must not require TC-004 to have run first. A dependent case becomes Blocked the moment its predecessor fails, and your suite loses coverage in a cascade.
- Atomic scope. One test case verifies one thing. A case titled "Verify login, dashboard and logout" reports a single Pass/Fail for three features — useless data.
- Write in the imperative present. "Click", "Enter", "Verify" — not "The tester should click".
Before and after¶
Poorly written case
Title: Test login Steps: Login to the app with correct details and see if it works. Expected: Should work fine.
The same case, rewritten
Title: TC_LOGIN_001 · Verify successful login with valid credentials
Preconditions: Active account qa.user@example.com exists; browser on /login.
Test Data: Username qa.user@example.com, Password Valid@Pass1
Steps:
1. Enter qa.user@example.com in the Username field.
2. Enter Valid@Pass1 in the Password field.
3. Click the Login button.
Expected Result:
1. Browser navigates to /dashboard within 3 seconds.
2. The header displays "Welcome, QA User".
3. The Logout link is visible in the top-right corner.
4. Status values and what they mean¶
| Status | Use when |
|---|---|
| Pass | Every expected result was observed |
| Fail | At least one expected result was not observed — raise a defect |
| Blocked | Could not execute due to an external problem (environment down, prerequisite defect) |
| Not Executed | Not yet run in this cycle |
| Skipped | Deliberately excluded — out of scope for this cycle |
| Deferred | Feature not ready; will be tested in a later cycle |
The distinction between Fail and Blocked matters for reporting. A 50-case suite reported as "10 pass, 40 fail" panics management. "10 pass, 2 fail, 38 blocked because the test database was offline" tells the truth.
5. The Requirement Traceability Matrix (RTM)¶
The RTM is a table that maps every requirement to the test cases covering it, and onward to any defects found. It answers three questions management always asks:
- Coverage: is every requirement tested? (Any requirement row with zero test cases is a coverage gap.)
- Impact: requirement REQ-AUTH-03 just changed — which test cases must I update? (Read across the row.)
- Quality: which requirements are producing the most defects?
Forward, backward, bidirectional¶
| Type | Direction | Answers |
|---|---|---|
| Forward | Requirements → test cases | Is every requirement covered by a test? |
| Backward | Test cases → requirements | Is every test justified, or are we testing things nobody asked for? |
| Bidirectional | Both | The complete picture — what most teams maintain |
A sample RTM¶
| Req ID | Requirement description | Test Case IDs | Cases | Executed | Passed | Failed | Defects | Status |
|---|---|---|---|---|---|---|---|---|
| REQ-AUTH-01 | User can log in with a registered email and password | TC_LOGIN_001 | 1 | 1 | 1 | 0 | — | ✅ Covered |
| REQ-AUTH-02 | Password field must mask input | TC_LOGIN_006 | 1 | 1 | 1 | 0 | — | ✅ Covered |
| REQ-AUTH-03 | Invalid credentials show a generic error message | TC_LOGIN_002, TC_LOGIN_003 | 2 | 2 | 1 | 1 | BUG-114 | ⚠️ Defect open |
| REQ-AUTH-04 | Account locks for 15 min after 5 failed attempts | TC_LOGIN_007 | 1 | 0 | 0 | 0 | — | ⏳ Not executed |
| REQ-AUTH-05 | Session expires after 30 minutes of inactivity | — | 0 | 0 | 0 | 0 | — | ❌ Coverage gap |
REQ-AUTH-05 is exactly what an RTM exists to surface: a requirement nobody wrote a test for. Without this table, it ships untested and nobody notices until a user complains.
Generic error messages are deliberate
Note that REQ-AUTH-03 says "generic". If the app says "Password incorrect" for a real account and "User not found" for a fake one, an attacker can enumerate valid accounts. This is why TC_LOGIN_002 and TC_LOGIN_003 must both expect the identical message — a security check hiding inside a functional test case.
6. What goes in a test plan (vs a test case)¶
Beginners often confuse these. A test plan is one document for the whole project; test cases are hundreds of small items.
A minimal test plan contains:
- Scope — what is being tested, and explicitly what is not.
- Test approach — manual vs automated, levels, types.
- Test environment — browsers, OS, devices, test data sources.
- Entry & exit criteria — when testing starts, when it is done.
- Schedule & effort estimate — cycles and dates.
- Roles & responsibilities — who executes, who triages, who signs off.
- Risks & mitigations — e.g. "third-party payment sandbox may be unstable → mock the gateway for regression runs."
- Deliverables — test cases, RTM, execution report, summary report.
You will write a real one in this level's project (Module 10).
Cheat sheet¶
| Artefact | One-line purpose |
|---|---|
| Test scenario | High-level what to test |
| Test case | Detailed, repeatable how to test it, with an exact expected result |
| Test suite | A grouped set of cases run together |
| Test data | The specific input values a case needs |
| Preconditions | State that must exist before step 1 |
| Test plan | The project-level strategy, scope and schedule document |
| RTM | Requirement ↔ test case ↔ defect mapping; proves coverage |
| Test summary report | End-of-cycle results and recommendation to release |
How It Actually Works¶
Techniques like equivalence partitioning and boundary value analysis
aren't just design habits — they're a direct response to combinatorial
explosion. A password field with rules on length (8–20), case, digits and
special characters has, in principle, an astronomically large input space;
you cannot execute even a small fraction of it. Partitioning collapses that
space into a handful of classes (valid, too-short, too-long, missing
uppercase, missing digit, missing special char) under the assumption that
every value inside one class exercises the same code path — because the
validation logic itself is almost always written as a small number of
branches (if length < 8, if !hasUppercase, etc.), one representative
value per branch achieves the same code coverage as testing every value in
that branch's range. Boundary analysis then targets exactly where those
branches flip: length == 7 and length == 8 are far more likely to expose
an off-by-one (< vs <=) than any value in the middle of the valid range,
because that's precisely where the comparison operator in the source code
makes its decision. An RTM works the same way in reverse: it's a manual
trace of the mapping from requirement to code path to test case, and a
requirement with zero mapped cases is a code path nobody has proven exists
correctly — the traceability matrix exists to make that gap visible before
release rather than after.
Exercise¶
Use this requirement set for a user registration form:
- REQ-REG-01 — The form has fields: Full Name, Email, Password, Confirm Password, and a "I accept the Terms" checkbox.
- REQ-REG-02 — Email must be unique across all accounts.
- REQ-REG-03 — Password must be 8–20 characters and contain at least one uppercase letter, one digit and one special character.
- REQ-REG-04 — Confirm Password must match Password.
- REQ-REG-05 — The Register button stays disabled until the Terms checkbox is ticked.
- REQ-REG-06 — On success, the user sees a "Verify your email" confirmation screen.
Then:
- Write three test scenarios covering this form.
- Write eight full test cases using the template from section 2 — complete with ID, preconditions, test data, numbered steps and specific expected results. At least five must be negative or boundary cases.
- Build an RTM with one row per requirement, listing which of your test case IDs cover it. Deliberately check whether any requirement ends up with zero cases — if so, write the missing case.
- Take your weakest test case and rewrite it applying all seven rules from section 3. Note in one sentence what specifically improved.