Test Scaffolding Generator
Automatically generate test scaffolding for untested code.
Testing Philosophy
Good tests are an investment, not a cost.
Core Beliefs
- Tests as Documentation: Tests show how code should be used
- Fast Feedback: Quick tests enable rapid development
- Confidence to Refactor: Good test coverage allows safe changes
- Regression Prevention: Tests catch bugs before production
Scope Balance
- Quick scaffolding (this skill): Fast test generation for single classes/functions
- Comprehensive suites (
/test-generatecommand): Full project test coverage with test plans - Manual refinement: Human review adds edge cases and business logic validation (essential for quality)
This skill provides rapid test scaffolding. For complete coverage, use comprehensive test generation + manual refinement.
When to Use This Skill
Activate this skill when the user:
- Shows new code and says "I need tests for this"
- Asks "how do I test this?"
- Mentions "no tests yet" or "untested code"
- Says "I should write tests" or "need test coverage"
- Shows a class/function and asks about testing
- Mentions specific test types: "unit test", "integration test", "e2e test"
Decision Framework
Before generating test scaffolding, determine:
What Type of Code Is This?
- Business logic function → Unit test (fast, isolated)
- Class with dependencies → Unit test with mocks/stubs
- API endpoint → Integration test (test with real dependencies)
- UI component → Component test (render, interactions)
- User flow → E2E test (full browser simulation)
What Test Framework?
PHP (Drupal/WordPress):
- PHPUnit for unit and integration tests
- Drupal Kernel tests for module testing
- WordPress test framework for plugins/themes
JavaScript:
- Jest for unit and component tests
- Cypress for E2E tests
- React Testing Library for React components
What Should Be Tested?
Unit tests (highest priority):
- ✅ Happy path - Expected behavior with valid input
- ✅ Edge cases - Boundary conditions (empty, null, zero, max)
- ✅ Error handling - Invalid input, exceptions
- ✅ Business logic - Calculations, transformations, decisions
Don't test (waste of time):
- ❌ Framework code (it's already tested)
- ❌ Simple getters/setters (no logic)
- ❌ Third-party libraries (trust their tests)
What Dependencies Need Mocking?
Mock/stub:
- ✅ External APIs (use fixtures instead)
- ✅ Database queries (use test database or mocks)
- ✅ File system operations (use virtual filesystem)
- ✅ Time-dependent code (mock date/time)
Don't mock:
- ❌ Code under test
- ❌ Simple data structures
- ❌ Pure functions
What Test Coverage Is Appropriate?
Critical code (90%+ coverage target):
- Authentication/authorization
- Payment processing
- Data writes/deletes
- Security-sensitive operations
Standard code (70-80% coverage target):
- Business logic
- API endpoints
- Public interfaces
Low priority (minimal coverage ok):
- Getters/setters
- Configuration
- UI styling
What Test Structure?
AAA pattern (standard):
- Arrange - Set up test data and mocks
- Act - Execute the code under test
- Assert - Verify expected outcomes
Test name convention:
test_methodName_scenario_expectedBehavior()- Example:
test_calculateTotal_withDiscount_returnsReducedPrice()
Decision Tree
User requests tests for code
↓
Analyze code type (function/class/endpoint/UI)
↓
Determine test type (unit/integration/e2e)
↓
Identify framework (PHPUnit/Jest/Cypress)
↓
Determine what to test (happy/edge/error)
↓
Identify dependencies to mock
↓
Generate test scaffolding with descriptive names
↓
Include AAA structure comments
Workflow
1. Analyze the Code to Test
Identify:
- Class name and namespace
- Methods to test (public methods)
- Dependencies (constructor parameters)
- Return types
- Drupal vs WordPress context
2. Determine Test Type
Unit Tests - For isolated logic:
- Services with minimal dependencies
- Utility functions
- Data transformation
- Business logic
Integration Tests - For component interaction:
- Controllers with database
- Form handlers
- API endpoints
- Complex workflows
E2E Tests - For user workflows:
- Login/authentication
- Multi-step forms
- Content creation
- Admin interfaces
3. Generate Appropriate Test Scaffold
Test Templates
Complete test templates are available for reference:
- Unit Test Templates - PHPUnit (Drupal/WordPress) & Jest
- Integration Test Templates - Functional tests & API testing
- E2E Test Templates - Cypress & Playwright
Use these templates as starting points, adapting for the specific code being tested.
Generation Strategy
1. Start Simple
Generate basic test structure first:
- Test class/describe block
- Setup/teardown methods
- One or two simple test cases
2. Identify Test Cases
For each public method:
- Happy path (valid input → expected output)
- Error cases (invalid input → exception)
- Edge cases (empty, null, boundary values)
- State changes (before/after verification)
3. Mock Dependencies
Identify what needs mocking:
- Database calls
- External APIs
- File system operations
- Time-dependent code
4. Add Assertions
Check:
- Return values
- State changes
- Side effects
- Error handling
Quick Response Patterns
For Simple Classes
When user shows a class with 2-3 methods:
- Identify the test type (unit vs integration)
- Generate test class with proper structure
- Create tests for each public method:
- Happy path test
- Error case test
- Edge case test (if applicable)
- Include setup/teardown as needed
- Add descriptive test names
Example Response:
"I'll generate PHPUnit tests for your UserManager class.
I see 3 public methods:
- getUser() - retrieves user data
- createUser() - creates new user
- deleteUser() - removes user
I'll create:
- Unit tests for getUser() (no database needed)
- Integration tests for createUser() and deleteUser() (require database)
[Generates test file with 6-8 test methods covering happy paths,
error cases, and edge cases]
This gives you ~80% coverage to start."
For WordPress Functions
When user shows WordPress function using WP APIs:
- Determine if unit or integration test
- Use WP_UnitTestCase for integration
- Use factories for test data
- Include setup/teardown for cleanup
Example Response:
"For WordPress functions using WP_Query, you'll want an integration test.
I'll generate a WP_UnitTestCase test that:
1. Creates test posts using the factory
2. Calls your function
3. Verifies the query results
4. Cleans up automatically in tearDown()
[Generates test code]
The test uses wp_insert_post() to create test data."
For Drupal Services
When user shows Drupal service with dependencies:
- Identify service dependencies
- Create mocks for dependencies in setUp()
- Generate unit tests with dependency injection
- Add @covers annotations
Example Response:
"I'll generate unit tests for your DataProcessor service.
I see it depends on:
- EntityTypeManagerInterface
- LoggerInterface
I'll:
1. Create mocks for these dependencies
2. Test each public method in isolation
3. Verify interactions with dependencies
4. Add @covers annotations for coverage tracking
[Generates test file with mocked dependencies]
This keeps tests fast by avoiding database calls."
For JavaScript/React Components
When user shows JS function or React component:
- Identify if pure function or component
- Use Jest for unit tests
- Use React Testing Library for components
- Mock external dependencies
Integration with CMS Cultivator
This skill complements the /test-generate slash command:
-
This Skill: Automatically triggered during conversation
- "I need tests for this class"
- "How do I test this function?"
- Quick single-class test generation
-
/test-generateCommand: Explicit batch generation- Generate tests for entire module
- Comprehensive test suite creation
- Project-wide test coverage
Best Practices
DO:
- ✅ Test behavior, not implementation details
- ✅ Use descriptive test names (
testCreateUserWithValidData()nottestCreateUser()) - ✅ Follow Arrange-Act-Assert pattern for clarity
- ✅ Keep tests independent (no dependencies between tests)
- ✅ Mock external dependencies (APIs, databases, filesystem)
- ✅ Clean up test data in tearDown()
- ✅ Test error cases and edge cases, not just happy path
- ✅ Keep tests fast (< 100ms for unit tests)
- ✅ Use factories or fixtures for test data
- ✅ Write tests before fixing bugs (TDD for bug fixes)
DON'T:
- ❌ Test private methods directly (test through public interface)
- ❌ Have multiple assertions testing different things (split into separate tests)
- ❌ Share state between tests (causes flaky tests)
- ❌ Test framework code or third-party libraries
- ❌ Use production database or live APIs in tests
- ❌ Leave test data behind (always clean up)
- ❌ Skip test setup to save time (leads to unclear tests)
- ❌ Copy-paste test code (extract helper methods)
- ❌ Use sleep() or arbitrary waits (use proper async patterns)
- ❌ Write tests that depend on test execution order
Example Interactions
Example 1: Simple class
User: "I wrote this UserManager class, need tests"
[Shows class with 3 methods]
Skill: "I'll generate PHPUnit tests for your UserManager class.
I see 3 public methods: createUser(), getUser(), deleteUser().
I'll create tests for the happy path and error cases for each.
[Generates test file]
This gives you 80% coverage to start. You may want to add edge case
tests for boundary conditions."
Example 2: WordPress function
User: "How do I test this WordPress function?"
[Shows custom function that uses WP_Query]
Skill: "For WordPress functions using WP_Query, you'll want an
integration test. I'll generate a WP_UnitTestCase test that:
1. Creates test posts using the factory
2. Calls your function
3. Verifies the query results
[Generates test code]
The test uses wp_insert_post() to create test data, then cleans up
automatically in tearDown()."
Example 3: React component
User: "Need tests for this React component"
[Shows UserProfile component]
Skill: "I'll create React Testing Library tests for your UserProfile component.
I see it:
- Displays user data from props
- Has edit button that calls onEdit callback
- Shows loading state
I'll generate tests for:
1. Rendering with user data
2. Clicking edit button
3. Loading state display
[Generates test file using React Testing Library]
These tests verify the component behavior from a user perspective."
Common Patterns
Testing Private Methods
Don't. Test public interface instead. If private method needs testing, consider extracting to separate class.
Testing Static Methods
// Avoid static methods when possible
// If you must, test directly
$result = MyClass::staticMethod($input);
$this->assertEquals($expected, $result);
Testing Database Operations
// Use transactions for rollback
protected function setUp(): void {
parent::setUp();
$this->database->beginTransaction();
}
protected function tearDown(): void {
$this->database->rollbackTransaction();
parent::tearDown();
}
Testing Async JavaScript
it('fetches user data', async () => {
const user = await fetchUser(123);
expect(user.name).toBe('John Doe');
});
// Or with promises
it('fetches user data', () => {
return fetchUser(123).then(user => {
expect(user.name).toBe('John Doe');
});
});
Platform-Specific Guidelines
Drupal Testing
- Use proper namespace:
Drupal\Tests\mymodule\Unit - Add @group annotation
- Add @covers annotation for coverage
- Use UnitTestCase for unit tests
- Use KernelTestBase for database tests
- Use BrowserTestBase for functional tests
WordPress Testing
- Extend WP_UnitTestCase
- Use factories for test data
- Follow WordPress naming:
test_method_name() - Use assertions:
$this->assertIsArray() - Clean up in tearDown()
JavaScript Testing
- Use describe() for grouping
- Use test() or it() for individual tests
- Use beforeEach() for setup
- Mock external dependencies
- Test user interactions, not implementation