A test case is a set of conditions under which a tester determines whether a feature works correctly. Well-written test cases are the backbone of effective testing.
Anatomy of a Test Case
Every test case should include:
| Field | Description |
|---|---|
| Test Case ID | Unique identifier (e.g., TC-LOGIN-001) |
| Title | Short description of what's being tested |
| Preconditions | What must be true before the test runs |
| Steps | Exact actions to perform |
| Test Data | Specific inputs to use |
| Expected Result | What should happen |
| Actual Result | What actually happened (filled during execution) |
| Status | Pass / Fail / Blocked / Skipped |
Example Test Case
Test Case ID: TC-LOGIN-001
Title: Successful login with valid credentials
Preconditions: User account exists with email test@example.com
Steps:
1. Navigate to /login
2. Enter "test@example.com" in the email field
3. Enter "ValidPass123!" in the password field
4. Click the "Sign In" button
Test Data: email=test@example.com, password=ValidPass123!
Expected Result: User is redirected to the dashboardTest Design Techniques
Equivalence Partitioning
Divide inputs into groups (partitions) where the system should behave the same way. Test one value from each partition instead of every possible value.
Example: An age field that accepts 18–65.
| Partition | Values | Expected |
|---|---|---|
| Below range | 0–17 | Rejected |
| Valid range | 18–65 | Accepted |
| Above range | 66+ | Rejected |
You only need three tests instead of testing every number from 0 to 100.
Boundary Value Analysis
Bugs love boundaries. Test the exact edges of each partition:
- 17 (just below valid) → Rejected
- 18 (lower boundary) → Accepted
- 65 (upper boundary) → Accepted
- 66 (just above valid) → Rejected
Decision Tables
When a feature has multiple conditions that combine to produce different outcomes, use a decision table:
| Condition | Rule 1 | Rule 2 | Rule 3 | Rule 4 |
|---|---|---|---|---|
| Valid email | Yes | Yes | No | No |
| Valid password | Yes | No | Yes | No |
| Action | Login success | Error: wrong password | Error: wrong email | Error: invalid credentials |
State Transition Testing
For features with distinct states, map the transitions:
[Logged Out] --login--> [Logged In] --timeout--> [Session Expired]
[Logged In] --logout--> [Logged Out]
[Session Expired] --refresh--> [Logged In]
[Session Expired] --ignore--> [Logged Out]Test each transition to verify the system moves between states correctly.
Positive vs Negative Testing
- Positive testing: Verify the system works with valid inputs ("happy path").
- Negative testing: Verify the system handles invalid inputs gracefully (empty fields, SQL injection, oversized files).
Both are essential. A system that only works on the happy path is fragile.
Writing Tips
- Be specific: "Enter a valid email" is vague. "Enter test@example.com" is testable.
- One thing per test case: Don't test login and password reset in the same case.
- Independent tests: Each test should work without relying on another test's outcome.
- Cover edge cases: Empty strings, max length, special characters, Unicode.