Test-Driven Development (TDD)
Most developers write code like this: Write Code โ Run App โ Fix Bugs. In TDD, we flip that on its head: Write Test โ Watch it Fail โ Write Code to Pass.
This might feel slow at first, but it prevents 90% of the bugs that usually crawl into your codebase during the "Fixing" stage.
The Red-Green-Refactor Cycleโ
This is the heartbeat of TDD. You repeat this cycle for every small feature you build.
1. RED: Write a Failing Testโ
Before you write a single line of application logic, you write a test for a feature that doesn't exist yet.
- Why? It defines exactly what your code should do.
- Result: The test fails because the function is missing or empty.
2. GREEN: Make it Passโ
Write the minimum amount of code required to make the test pass. Don't worry about "clean code" yetโjust make the light turn green.
- Why? It keeps you focused on the specific goal.
- Result: The test passes.
3. REFACTOR: Clean it Upโ
Now that you have a "Safety Net" (the passing test), you can clean up your code. Rename variables, remove duplication, and optimize.
- Why? It ensures your code stays professional and maintainable.
- Result: The code is beautiful, and the test still passes.
TDD in Action: A Password Validatorโ
Let's build a password validator for CodeHarborHub using TDD.
Step 1: RED (The Test)โ
We want a function that returns false if the password is less than 8 characters.
import { isSecure } from './validator';
test('should return false if password is less than 8 characters', () => {
expect(isSecure('12345')).toBe(false); // This fails because isSecure doesn't exist!
});
Step 2: GREEN (The Code)โ
We write just enough code to pass.
export const isSecure = (password) => {
return password.length >= 8;
};
Run the test: Passed!
Step 3: REFACTORโ
Maybe we want to rename the variable for better clarity.
export const isSecure = (pwd) => {
const MIN_LENGTH = 8;
return pwd.length >= MIN_LENGTH;
};
Run the test again: Still Passed!
Why use TDD at CodeHarborHub?โ
| Feature | Without TDD | With TDD |
|---|---|---|
| Bugs | Found late (by users) | Found early (by you) |
| Code Quality | Messy (hard to fix later) | Clean (Refactored safely) |
| Requirements | Vague | Crystal Clear (The Tests) |
| Confidence | "I think it works..." | "I know it works!" |
When NOT to use TDD?โ
While TDD is amazing for core logic (like auth, payments, and math), it's not always the best for:
- UI/CSS: Hard to test "if it looks pretty" with a script.
- Prototyping: If you are just "exploring" an idea and don't know what the output should be yet.
Summary Checklistโ
- I understand the Red-Green-Refactor cycle.
- I know that TDD means writing the test before the code.
- I understand that TDD acts as a blueprint for my logic.
- I know that "Refactor" means cleaning code without changing its behavior.
TDD feels like "extra work" for the first week. But after your first giant project where you change 100 lines of code and know it's still safe because of your tests, you'll never go back!