TDD cycle: Red → Green → Refactor
// 1. RED — Write a failing test first
public function testPasswordMustHaveUppercase(): void {
$validator = new PasswordValidator();
$this->assertFalse($validator->validate("alllowercase1!"));
}
// 2. GREEN — Write minimum code to pass
class PasswordValidator {
public function validate(string $password): bool {
return preg_match("/[A-Z]/", $password) === 1;
}
}
// 3. REFACTOR — improve without breaking tests
class PasswordValidator {
private array $rules = [
"uppercase" => "/[A-Z]/",
"digit" => "/[0-9]/",
"special" => "/[!@#$%]/",
"length" => "/.{8,}/",
];
public function validate(string $password): bool {
foreach ($this->rules as $rule => $pattern) {
if (!preg_match($pattern, $password)) return false;
}
return true;
}
}
// 4. Repeat for next feature