name: write-validator-test description: Creates PHPUnit test cases for Validator methods in tests/Detain/Tests/ZipZapper/ValidatorTest.php following existing patterns. Use when user says 'add test', 'write test for country', 'test isValid', 'test getFormats', 'test hasCountry', or 'test getZipName'. Covers isValid(), hasCountry(), getFormats(), getZipName(), and ValidationException throwing. Do NOT use for integration tests, parser tests, or bin/parse.php testing.
write-validator-test
Critical
- All tests go in
tests/Detain/Tests/ZipZapper/ValidatorTest.php— never create a separate test file. - Namespace must be
Detain\Tests\ZipZapper; use statements must beDetain\ZipZapper\ValidatorandPHPUnit\Framework\TestCase. - Every test method instantiates its own
new Validator()— no sharedsetUp()instance. @expectedExceptiondocblock annotation is the project pattern for exception tests — do NOT use$this->expectException()(PHPUnit 5/6 style used here).- Indentation: tabs only (per
.scrutinizer.yml). - Run
vendor/bin/phpunit tests/ -vafter every change to confirm no regressions.
Instructions
Identify what to test. Determine which method and country code the user wants covered. Check
src/Validator.php$formatsarray to confirm the country code exists and note its format strings. Check$zipNamesif testinggetZipName().- Verify the country code is present in
$formatsbefore writing the test.
- Verify the country code is present in
Name the test method. Follow the pattern
test{CountryAdjective}Code()forisValid()country tests (e.g.,testCanadianCode,testJapaneseCode). For other methods use descriptive names:testZipName,testGetFormats,testHasCountry,testInvalidCountryCode,testGetFormatsWithInvalidCountryCode.- Verify no method with the same name already exists in the file before adding.
Write a valid-code assertion. For
isValid()tests, assert at least one real postal code that matches the country's format:public function testCanadianCode() { $validator = new Validator(); $this->assertTrue($validator->isValid('CA', 'K1A 0B1')); }Add a false assertion when the format is strict. If the format requires a space (e.g.,
'@#@ #@#','### ##') include anassertFalsefor the no-space version and aassertTruewith$ignoreSpaces = true:$this->assertFalse($validator->isValid('CA', 'K1A0B1')); $this->assertTrue($validator->isValid('CA', 'K1A0B1', true));- Only add this when the format string contains a literal space character.
Test
getFormats(). Assert the exact array from$formats:public function testGetFormats() { $validator = new Validator(); $this->assertEquals(['@#@ #@#'], $validator->getFormats('CA')); }Test
getZipName(). Check both a country in$zipNamesand the fallback default:public function testZipName() { $validator = new Validator(); $this->assertEquals('ZIP code', $validator->getZipName('US')); $this->assertEquals('Postal Code', $validator->getZipName('invalid_country_code')); }Test
hasCountry(). Assert true for a known code and false for an invalid one:public function testHasCountry() { $validator = new Validator(); $this->assertTrue($validator->hasCountry('US')); $this->assertFalse($validator->hasCountry('invalid_country_code')); }Test
ValidationExceptionthrowing. Use@expectedExceptiondocblock — one method forisValid(), one forgetFormats():/** * @expectedException Detain\ZipZapper\ValidationException */ public function testInvalidCountryCode() { $validator = new Validator(); $validator->isValid('XXXXXX', 'YYYYYY'); } /** * @expectedException Detain\ZipZapper\ValidationException */ public function testGetFormatsWithInvalidCountryCode() { $validator = new Validator(); $validator->getFormats('invalid_country_code'); }Insert new methods before the closing
}of the class. Append; do not reorder existing tests.Run tests to confirm green:
vendor/bin/phpunit tests/ -v
Examples
User says: "Add a test for Canadian postal codes"
Actions taken:
- Check
src/Validator.php—'CA' => ['@#@ #@#']found. - Method name:
testCanadianCode(not already in file). - Format has a space → add
assertFalse(no-space) andassertTruewith$ignoreSpaces = true.
Result added to ValidatorTest.php:
public function testCanadianCode()
{
$validator = new Validator();
$this->assertTrue($validator->isValid('CA', 'K1A 0B1'));
$this->assertFalse($validator->isValid('CA', 'K1A0B1'));
$this->assertTrue($validator->isValid('CA', 'K1A0B1', true));
}
User says: "Test getZipName for German"
Actions taken:
- Check
$zipNames—'DE' => ['name' => 'PLZ', ...]found.
Result:
public function testZipName()
{
$validator = new Validator();
$this->assertEquals('PLZ', $validator->getZipName('DE'));
$this->assertEquals('Postal Code', $validator->getZipName('invalid_country_code'));
}
(Update existing testZipName if already present; don't duplicate.)
Common Issues
Call to undefined method ... getZipName()— you are testing a method that does not exist in the installed version. Rungrep -n 'getZipName' src/Validator.phpto confirm the method name spelling.- Test passes but wrong format tested — you used a postal code that matches a different country's format. Derive test values from the exact format string in
$formats:#→ any digit,@→ any letter. @expectedExceptionhas no effect / test always passes — confirm PHPUnit version withvendor/bin/phpunit --version. This project targets PHPUnit 4/5 annotation style. Do NOT switch to$this->expectException().- Tab vs space IndentationError from phpcs — the
.scrutinizer.ymlenforces tabs. If your editor inserts spaces, convert:unexpand --first-only -t 4 file.php. Class 'Detain\ZipZapper\ValidationException' not found— runcomposer dump-autoloadto regenerate the classmap after any new file additions.- Duplicate method name — PHPUnit will silently run only the last definition. Always
grep testMethodName tests/Detain/Tests/ZipZapper/ValidatorTest.phpbefore adding.