Awesome-claude-code testing-knowledge
Testing knowledge base for PHP 8.4 projects. Provides testing pyramid, AAA pattern, naming conventions, isolation principles, DDD testing guidelines, and PHPUnit patterns.
install
source · Clone the upstream repo
git clone https://github.com/dykyi-roman/awesome-claude-code
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/dykyi-roman/awesome-claude-code "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/testing-knowledge" ~/.claude/skills/dykyi-roman-awesome-claude-code-testing-knowledge && rm -rf "$T"
manifest:
skills/testing-knowledge/SKILL.mdsource content
Testing Knowledge Base
Quick reference for PHP testing patterns, principles, and best practices.
Testing Pyramid
/\ / \ Functional (10%) /────\ - E2E, browser tests / \ - Slow, fragile /────────\ Integration (20%) / \ - DB, HTTP, queues /────────────\Unit (70%) / \- Fast, isolated /________________\- Business logic
Rule: 70% unit, 20% integration, 10% functional. Invert the pyramid = slow, brittle test suite.
AAA Pattern (Arrange-Act-Assert)
public function test_order_calculates_total_with_discount(): void { // Arrange — set up test data $order = new Order(OrderId::generate()); $order->addItem(new Product('Book', Money::EUR(100))); $discount = new PercentageDiscount(10); // Act — execute the behavior $total = $order->calculateTotal($discount); // Assert — verify the outcome self::assertEquals(Money::EUR(90), $total); }
Rules:
- One blank line between sections
- Single Act per test
- Assert behavior, not implementation
Naming Conventions
PHPUnit Style
test_{method}_{scenario}_{expected}
| Example | Method | Scenario | Expected |
|---|---|---|---|
| calculateTotal | with discount | returns reduced amount |
| confirm | when already shipped | throws exception |
| Email (VO) | with invalid format | fails validation |
Pest Style
it('calculates total with discount applied') it('throws exception when confirming shipped order') it('fails validation for invalid email format')
Test Isolation Principles
DO
- Fresh fixtures per test
- Independent test execution (any order)
- Teardown cleans all state
- Use in-memory implementations
DON'T
- Shared mutable state between tests
- Tests depending on execution order
- Global variables or singletons
- Real external services in unit tests
Quick Quality Checklist
| Rule | Check |
|---|---|
| One test = one behavior | Single assertion group |
| Test is documentation | Name reads as specification |
| No logic in tests | No if/for/while |
| Fast execution | <100ms per unit test |
| Mock interfaces only | Never mock VO, Entity, final |
| ≤3 mocks per test | More = design smell |
| Behavior over implementation | Test WHAT, not HOW |
DDD Component Testing
| Component | Test Focus | Mocks Allowed |
|---|---|---|
| Value Object | Validation, equality, immutability | None |
| Entity | State transitions, business rules | None |
| Aggregate | Invariants, consistency, events | None |
| Domain Service | Business logic spanning aggregates | Repository (Fake) |
| Application Service | Orchestration, transactions | Repository, EventDispatcher |
| Repository | CRUD operations | Database (SQLite) |
PHP 8.4 Test Patterns
Unit Test Template
<?php declare(strict_types=1); namespace Tests\Unit\Domain; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\TestCase; #[Group('unit')] #[CoversClass(Email::class)] final class EmailTest extends TestCase { public function test_creates_valid_email(): void { $email = new Email('user@example.com'); self::assertSame('user@example.com', $email->value); } public function test_throws_for_invalid_format(): void { $this->expectException(InvalidArgumentException::class); new Email('invalid'); } }
Integration Test Template
<?php declare(strict_types=1); namespace Tests\Integration\Infrastructure; use PHPUnit\Framework\Attributes\Group; use Tests\DatabaseTestCase; #[Group('integration')] final class DoctrineOrderRepositoryTest extends DatabaseTestCase { private OrderRepositoryInterface $repository; protected function setUp(): void { parent::setUp(); $this->repository = $this->getContainer()->get(OrderRepositoryInterface::class); } public function test_saves_and_retrieves_order(): void { // Arrange $order = OrderMother::pending(); // Act $this->repository->save($order); $found = $this->repository->findById($order->id()); // Assert self::assertNotNull($found); self::assertTrue($order->id()->equals($found->id())); } }
Test Doubles Quick Reference
| Type | Purpose | When to Use |
|---|---|---|
| Stub | Returns canned answers | External API responses |
| Mock | Verifies interactions | Event publishing |
| Fake | Working implementation | InMemory repository |
| Spy | Records calls | Logging, notifications |
Decision Matrix
Need to verify a call was made? ├── Yes → Mock or Spy └── No → Need real behavior? ├── Yes → Fake └── No → Stub
Common Test Smells
| Smell | Detection | Fix |
|---|---|---|
| Logic in Test | , , in test | Extract to helper or parameterize |
| Mock Overuse | >3 mocks | Refactor design, use Fakes |
| Mystery Guest | External files, hidden data | Inline test data or use Builder |
| Eager Test | Tests multiple behaviors | Split into separate tests |
| Fragile Test | Breaks on refactor | Test behavior, not implementation |
Advanced Testing Patterns
Contract Testing (Pact)
| Aspect | Unit Test | Integration Test | Contract Test |
|---|---|---|---|
| Speed | Fast | Slow | Medium |
| Scope | Single class | Service + deps | API boundary |
| Isolation | Full | Partial | Consumer/Provider |
| Use case | Business logic | DB, queues | Service-to-service |
When to use: Microservices REST APIs, message-based systems, event schema verification.
Load Testing Patterns
| Pattern | Duration | Load Profile | Goal |
|---|---|---|---|
| Smoke | 1-2 min | Minimal | Verify script works |
| Load | 10-30 min | Expected traffic | Performance baseline |
| Stress | 10-30 min | 1.5-2x expected | Find breaking point |
| Spike | 5-10 min | Sudden burst | Test auto-scaling |
| Soak | 2-8 hours | Sustained | Find memory leaks |
Chaos Testing (Failure Injection)
| Failure | How to Inject | What It Tests |
|---|---|---|
| Network latency | Sleep in middleware | Timeout handling |
| Service error | Return 500 randomly | Circuit breaker |
| Connection refused | Close port | Fallback behavior |
| Slow database | Query delay | Query timeout handling |
E2E Distributed Testing
| Strategy | How | Trade-off |
|---|---|---|
| Test containers | Docker Compose per test | Isolated but slow |
| Shared staging | Dedicated environment | Fast but interference |
| Data seeding | API/DB setup per test | Controlled but complex |
| Snapshot restore | DB snapshot before tests | Fast reset |
References
For detailed information, load these reference files:
— Unit test patterns and examplesreferences/unit-testing.md
— Integration test setup and patternsreferences/integration-testing.md
— Testing DDD components (VO, Entity, Aggregate, Service)references/ddd-testing.md
— Contract testing (Pact), chaos testing, load testing patterns (ramp-up, spike, soak), E2E distributed testingreferences/advanced-testing.md