This guide covers the comprehensive test suite for the PivotPHP ReactPHP extension.
Standard unit tests covering individual components:
# Run all unit tests
composer test
# Run with coverage report
composer test:coverageSpecial test suites for performance, stress, and long-running scenarios:
# Run all performance tests
composer test:performance
# Run specific test groups
composer test:benchmark # Benchmark tests
composer test:stress # Stress tests
composer test:long-running # Long-running stability testsLocated in tests/ directory:
- Bridge Tests: Request/Response conversion between ReactPHP and PivotPHP
- Security Tests: Request isolation, blocking code detection, memory management
- Integration Tests: Full server integration with PivotPHP application
- Middleware Tests: Security middleware functionality
Located in tests/Performance/ directory:
Measures baseline performance for different route types:
- Minimal route response time
- JSON response handling
- Middleware processing overhead
- Database query simulation
- Complex computation handling
- Concurrent request throughput
Tests system behavior under high load:
- High concurrent request handling (100-1000 concurrent requests)
- Memory stability under load
- CPU-intensive request handling
- Large response streaming
- Error recovery and resilience
Validates stability over extended periods:
- Memory leak detection over time
- Global state isolation persistence
- Resource management (file handles, connections)
- Cache growth management
- Event loop stability
# Quality check (code style, static analysis, unit tests)
composer quality:check
# Run specific test file
./vendor/bin/phpunit tests/Security/BlockingCodeDetectorTest.php
# Run tests with filter
./vendor/bin/phpunit --filter testDetectsSleepFunctionPerformance tests are marked as skipped by default to prevent accidental execution. To run them:
# Remove skip annotations or run with --no-skip flag
./vendor/bin/phpunit -c phpunit-performance.xml --group=benchmark
# Run with custom memory limit
php -d memory_limit=1G vendor/bin/phpunit -c phpunit-performance.xml
# Run manual stress tests (recommended)
php scripts/stress-test.phpFor comprehensive stress testing, use the dedicated manual script:
# Run all stress tests
php scripts/stress-test.php
# The script includes:
# - High concurrent requests testing
# - Memory usage monitoring under load
# - CPU intensive workload testing
# - Large response handling
# - Error recovery validationFor CI environments, use only unit tests:
# .github/workflows/tests.yml example
- name: Run tests
run: composer testpublic function testRequestBridgeConvertsHeaders(): void
{
$reactRequest = new ServerRequest(
'POST',
new Uri('http://example.com/api'),
['Content-Type' => 'application/json']
);
$psrRequest = $this->bridge->convertFromReact($reactRequest);
$this->assertEquals('application/json', $psrRequest->getHeaderLine('Content-Type'));
}public function testCallbackInvocation(): void
{
$expectedArgs = ['arg1', 'arg2'];
$actualCallback = function ($arg1, $arg2) {
return $arg1 . $arg2;
};
[$wrapper, $verifier] = AssertionHelper::createCallbackVerifier($this, $actualCallback, $expectedArgs);
// Use the wrapper in your test
$result = $wrapper('arg1', 'arg2');
// Verify the callback was called with correct arguments
$verifier();
$this->assertEquals('arg1arg2', $result);
}public function testMissingHostHeader(): void
{
// Remove automatically added Host header
$request = (new ServerRequest(
'GET',
new Uri('http://example.com/test'),
[]
))->withoutHeader('Host');
$response = $this->middleware->process($request, $handler);
// Assert specific status code, not ranges
$this->assertEquals(400, $response->getStatusCode());
}/**
* @group stress
*/
public function testHighLoad(): void
{
$this->markTestSkipped('Stress tests should be run manually');
// Test implementation
}- Isolation: Each test should be independent
- Cleanup: Always clean up resources in
tearDown() - Assertions: Use specific assertions for clarity
- Mocking: Mock external dependencies
- Performance: Skip heavy tests by default
- Output Buffer Management: TestCase automatically handles output buffer isolation
- Callback Testing: Use AssertionHelper::createCallbackVerifier() for proper callback verification
- Error Assertions: Assert specific status codes rather than ranges for clear expectations
Two configuration files are provided:
phpunit.xml: Standard unit testsphpunit-performance.xml: Performance test suite
Set these for testing:
export REACTPHP_TEST_HOST=127.0.0.1
export REACTPHP_TEST_PORT=18080
export REACTPHP_TEST_TIMEOUT=30# Run with verbose output
./vendor/bin/phpunit -v
# Show test execution flow
./vendor/bin/phpunit --debug// Add to test
$this->memoryGuard->startMonitoring();
$this->memoryGuard->onMemoryLeak(function ($data) {
var_dump($data);
});Performance tests output detailed metrics after completion:
Benchmark Results:
==================
minimal_route:
Iterations: 1000
Avg Time: 0.8421 ms
P95: 1.2000 ms
Throughput: 1187.65 req/s
# Increase memory limit for tests
php -d memory_limit=512M vendor/bin/phpunit// Always stop the loop in tearDown
protected function tearDown(): void
{
Loop::get()->stop();
parent::tearDown();
}# Use different port for tests
export REACTPHP_TEST_PORT=18081When adding new features:
- Write unit tests first (TDD approach)
- Add integration tests for server interaction
- Consider performance implications
- Document any special test requirements
Example PR checklist:
- Unit tests added/updated
- Integration tests if applicable
- Performance tests for critical paths
- All tests passing locally
- Documentation updated