test-validator
PHP Test Validator
A specialized skill for validating PHP test files in CakePHP projects, particularly focused on strict testing principles that ensure tests guarantee production code behavior.
Configuration
This skill reads project-specific test rules from:
- Project's CLAUDE.md - testing rules and constraints
tests/README.md- Project test documentation (default)
Core Principle
Test code exists to guarantee the functionality of production code. Code that contradicts this purpose is prohibited.
All validation rules derive from this principle. Tests must:
- Execute production code paths
- Use production configuration
- Verify actual behavior, not code structure
Derived Requirements
The core principle implies:
-
Guarantee Traceability: Each guarantee item (保証対象) must correspond to a concrete branch or behavior in the
@coverstarget method. Read the production code first; describe the code's actual behavior, not the test's intent. -
Assertion Distinguishability: When multiple code paths produce the same observable output (e.g., same redirect URL, same HTTP status), a single assertion on that output is insufficient. Additional verification (DB state, response body, side effects) is required to prove which path was exercised.
Core Validation Rules
1. Test Documentation Format
Default requirements:
@coversannotation specifying the target class/method@groupannotation for test categorization- Clear test method naming (
test<Action><ExpectedBehavior>)
Example:
/**
* @covers \App\Controller\UsersController::index
* @group integration
*/
public function testIndexReturnsUserList(): void
{
$this->get('/users');
$this->assertResponseOk();
}
2. Configure::read() Usage Validation
Required Pattern:
- Use
Configure::read()for all configuration values - Never hardcode status values or flags
- Include
use Cake\Core\Configure;statement in fixtures
Check for violations:
// ❌ WRONG: Hardcoded value
$status = 5;
// ✅ CORRECT: Using Configure::read
$status = Configure::read('Application.Status.applying');
3. Prohibited Patterns Detection
All patterns violate the core principle. See tests/README.md for project-specific examples.
Critical Violations:
| # | Category | Pattern | Why Prohibited |
|---|---|---|---|
| 1 | Conditional | if, ??, try-catch with assertions |
Result depends on execution path |
| 2 | Config Override | Configure::write() |
Test uses different config than production |
| 3 | Missing @covers | Test without @covers annotation |
Coverage target unknown |
| 4 | Existence Check | method_exists(), class_exists() |
Tests code structure, not behavior |
| 5 | Placeholder | markTestSkipped(), assertTrue(true) |
No actual verification |
| 6 | PHPDoc Content | NOTE:, dates, impl notes in PHPDoc |
Spec only, no implementation details |
| 7 | Defensive Definition | if (!defined()) { define(); } |
Masks production errors where constant is undefined |
| 8 | Shallow Assertion | Only assertResponseOk() without business logic verification |
Tests HTTP status, not actual functionality |
| 9 | Guarantee not traceable to @covers branch | Describes a concept the @covers target does not implement |
Guarantee must map to actual code branch |
| 10 | Indistinguishable assertions for different code paths | Same observable output used to assert both success and error paths | Additional verification required to distinguish paths |
| - | Mock Production | Mock Components, Models, Helpers | Business logic not tested |
| - | Schema Override | _initializeSchema in Model |
DB schema diverges from migration |
| - | Direct Data | newEntity() without Fixture |
Test data diverges from production |
Rule 7 - Defensive Definition Details:
Test code should NOT protect against undefined constants, classes, or functions. If production code requires them, the test should fail when they're missing.
// ❌ WRONG: Defensive definition masks production errors
if (!defined('APP_VERSION')) {
define('APP_VERSION', '1.0.0');
}
// ❌ WRONG: Defensive class existence check
if (!class_exists('SomeService')) {
class SomeService { /* mock */ }
}
// ✅ CORRECT: Let the test fail if constant is undefined
// Production code should define APP_VERSION; test should verify it exists
$this->assertNotEmpty(APP_VERSION);
Rule 8 - Shallow Assertion Details:
assertResponseOk() only verifies HTTP 2xx status. It does NOT verify:
- Response body content matches expected data
- Database state changed correctly
- Business rules were applied
// ❌ WRONG: Only checks HTTP status
public function testCreateUser(): void
{
$this->post('/users', ['name' => 'John']);
$this->assertResponseOk(); // Passes even if user wasn't created!
}
// ✅ CORRECT: Verify actual business outcome
public function testCreateUser(): void
{
$this->post('/users', ['name' => 'John']);
$this->assertResponseOk();
// Verify database state
$user = $this->Users->find()->where(['name' => 'John'])->first();
$this->assertNotNull($user);
$this->assertEquals('John', $user->name);
// Or verify response content
$this->assertResponseContains('User created successfully');
}
4. Production Code Verification
Check that test targets existing production code:
- Controller file exists
- Action method exists
- Route is defined
- URL pattern matches
5. Test Command Validation
Use the test command defined in the project's CLAUDE.md.
Validation rules:
- Only use the test command specified in CLAUDE.md
- Do NOT run test commands directly (e.g.,
composer test,vendor/bin/phpunit) unless specified - Check project instructions before executing tests
6. Specification Alignment Validation
Validates alignment between test documentation (README.md) and actual test code.
Alignment Checks:
- Test function names match documentation
- Implementation status markers are accurate
- Test counts per category are correct
- Consolidation notes are documented
Integrity Score:
Score = (Matching Functions / Total Functions in README) × 100
100: Perfect alignment
90-99: Minor discrepancies
70-89: Moderate misalignment - fix before PR
0-69: Critical misalignment - fix immediately
When to Run:
- After test code is written or modified
- Before creating PR or committing test changes
- During quality review
Validation Process
When analyzing a test file:
- Load project rules - Read tests/README.md for project-specific prohibitions
- Parse PHPDoc blocks - Check for required annotations (@covers, @group, etc.)
- Scan for hardcoded values - Identify potential Configure::read violations
- Detect prohibited patterns - Check against core + project-specific patterns
- Verify production code - Confirm controller/action/route existence
- Check fixture compliance - Ensure proper fixture usage patterns
- Validate specification alignment - Compare README.md with actual test code
Output Format
Return validation results as:
✅ PASS: [Description of what passed]
❌ FAIL: [Description of violation]
Line X: [Code snippet or issue]
Fix: [Suggested correction]
⚠️ WARN: [Non-critical issue]
Examples
Example 1: Validating test documentation
// Input: Test method without proper documentation
public function testIndex(): void
{
$this->get('/user/users');
$this->assertResponseOk();
}
// Output:
❌ FAIL: Missing required PHPDoc documentation
Line 1: testIndex() lacks @covers annotation
Fix: Add PHPDoc with @covers specifying the target class/method
Example 2: Detecting Configure::write violation
// Input: Test with configuration override
public function testWithConfig(): void
{
Configure::write('App.setting', 'test-value');
// ...
}
// Output:
❌ FAIL: Prohibited pattern - Configure::write in test
Line 3: Configure::write('App.setting', 'test-value')
Fix: Use actual production configuration value with Configure::read()
Example 3: Conditional assertion violation
// Input: Test with conditional logic
public function testWithCondition(): void
{
$result = $this->service->process();
if ($result !== null) {
$this->assertEquals($expected, $result);
} else {
$this->markTestSkipped('No data');
}
}
// Output:
❌ FAIL: Prohibited pattern - Conditional assertion
Line 4-8: if/else block with assertions
Fix: Remove conditional; test should have deterministic expected outcome
Example 4: Existence check violation
// Input: Test checking code structure instead of behavior
public function testMethodExists(): void
{
$this->assertTrue(method_exists($this->controller, 'index'));
}
// Output:
❌ FAIL: Prohibited pattern - Existence check
Line 3: method_exists() tests code structure, not behavior
Fix: Call the method and verify its actual output/behavior
Integration with CakePHP Projects
This skill is specifically designed for:
- CakePHP 4.x/5.x projects
- Multi-tenant database architectures
- Projects following strict test principles
- PHP 8.x codebases
Project Rules: tests/README.md and project CLAUDE.md
Usage Notes
- Read
tests/README.mdfirst to load project-specific rules - Run validation before committing test files
- Integrity score must be >= 90 for PR approval
- All ERROR severity issues must be resolved before merge
- Particularly important during PHP/CakePHP version upgrades
Used By Agents
- quality-reviewer: Validates test code during code review
- test-developer: Validates test quality during implementation
- deliverable-evaluator: Gate-check before commit/PR
Related Skills
This skill supersedes test-spec-validator (now integrated):
- Test code quality validation (PHPDoc, assertions, patterns)
- README.md ↔ test code alignment validation
More from masanao-ohba/claude-manifests
requirement-analyzer
Invoke when goal-clarifier analyzes user requirements to extract goals and constraints. Provides structured requirement decomposition into functional/non-functional categories, stakeholder mapping, assumption identification, and documentation format.
37test-case-designer
Invoke when test-strategist plans test coverage for CakePHP features. Produces categorized test case specifications (unit/integration/system) with CakePHP-specific fixtures, IntegrationTestTrait usage, and proper test documentation format.
26functional-designer
Invoke when design-architect creates functional specs for CakePHP features. Produces detailed technical specifications mapping requirements to CakePHP controllers, models, services, and views with data flow diagrams and API endpoint definitions.
18react-architectural-patterns
Invoke when design-architect or code-developer designs React 19 component architecture. Provides component type taxonomy, composition patterns, state management strategies, render optimization techniques, and React 19 feature guidance.
15nextjs-code-reviewer
Invoke when quality-reviewer reviews Next.js 15 App Router code. Provides framework-specific review checklist covering file organization, server/client component usage, data fetching correctness, metadata configuration, and performance patterns.
14security-patterns
Invoke when code-developer or quality-reviewer handles PHP security concerns. Provides input validation patterns, SQL injection prevention, XSS protection, CSRF mitigation, secure session management, and password hashing best practices for PHP.
14