volt-test / laravel-performance-testing
A Laravel package for performance testing with VoltTest
Installs: 1 223
Dependents: 0
Suggesters: 0
Security: 0
Stars: 66
Watchers: 1
Forks: 1
Open Issues: 0
pkg:composer/volt-test/laravel-performance-testing
Requires
- php: ^8.2
- ext-pcntl: *
- illuminate/support: ^10.0|^11.0|^12.0
- volt-test/php-sdk: ^1.0.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.14
- orchestra/testbench: ^10.0
- phpstan/phpstan: ^1.10
- phpstan/phpstan-deprecation-rules: ^1.1
- phpunit/phpunit: ^11.5.3
Suggests
- phpunit/phpunit: Required for PHPUnit integration features.
This package is auto-updated.
Last update: 2025-11-29 17:34:32 UTC
README
A Laravel package for performance testing with the VoltTest PHP SDK. Easily create and run load tests for your Laravel applications with built-in route discovery, CSRF handling, and comprehensive reporting.
This package is built on top of the VoltTest PHP SDK and provides a seamless Laravel integration layer with additional Laravel-specific features like automatic route discovery, CSRF token handling, and Artisan commands.
For more information about the core VoltTest functionality, visit php.volt-test.com.
Table of Contents
- About Laravel Performance Testing VoltTest
- Requirements
- Features
- Installation
- Configuration
- Quick Start
- Creating Tests
- API Testing
- Available Methods
- Running Tests
- Reports
- CSV Data Sources
- PHPUnit Integration
- Advanced Configuration
- Testing Tips
- Troubleshooting
- Learn More
About Laravel Performance Testing VoltTest
This Laravel package extends the VoltTest PHP SDK with Laravel-specific functionality. While the core VoltTest PHP SDK provides the foundation for performance testing, this package adds:
- Laravel Integration - Service provider, facades, and configuration
- Artisan Commands - CLI commands for test creation and execution
- Route Discovery - Automatic Laravel route detection and test generation
- Laravel Scenarios - Enhanced scenario class with Laravel-specific methods
For comprehensive documentation about VoltTest core features, load testing concepts, and advanced configuration options, please visit php.volt-test.com.
Requirements
- PHP 8.2+
- VoltTest PHP SDK 1.1.0+
Features
- Easy Laravel Integration - Seamlessly integrates with Laravel applications
- Automatic Route Discovery - Discover and test your application routes automatically
- Comprehensive Reporting - Detailed performance reports with metrics
- URL Load Testing - Direct URL testing without creating test classes
- Artisan Commands - Convenient CLI commands for test creation and execution
- Configurable - Flexible configuration options for different environments
- PHPUnit Integration - Run performance tests within your PHPUnit test suite with automated server management and assertions
- CSV Data Sources - Load dynamic test data from CSV files for realistic performance testing
Installation
You can install the package via Composer:
composer require volt-test/laravel-performance-testing --dev
The package will automatically register its service provider.
Publish the configuration file:
php artisan vendor:publish --tag=volttest-config
Configuration
The configuration file config/volttest.php contains all the settings for your performance tests:
return [ // Test Configuration 'name' => env('VOLTTEST_NAME', 'Laravel Application Test'), 'description' => env('VOLTTEST_DESCRIPTION', 'Performance test for Laravel application'), // Load Configuration 'virtual_users' => env('VOLTTEST_VIRTUAL_USERS', 10), 'duration' => env('VOLTTEST_DURATION'), // e.g., '1m', '30s', '2h' 'ramp_up' => env('VOLTTEST_RAMP_UP', null), // Debug Configuration 'http_debug' => env('VOLTTEST_HTTP_DEBUG', false), // Test Paths 'test_paths' => app_path('VoltTests'), // Reports 'reports_path' => storage_path('volttest/reports'), 'save_reports' => env('VOLTTEST_SAVE_REPORTS', true), // Base URL 'use_base_url' => env('VOLTTEST_USE_BASE_URL', true), 'base_url' => env('VOLTTEST_BASE_URL', 'http://localhost:8000'), // CSV Data Source Configuration 'csv_data' => [ 'path' => storage_path('volttest/data'), // Default CSV location 'validate_files' => true, // Check file exists before run 'default_distribution' => 'unique', // Default distribution mode 'default_headers' => true, // Default header setting ], ];
Quick Start
1. Create Your First Test
Generate a new performance test with route discovery:
php artisan volttest:make UserTest --routes --select
This creates a test class at app/VoltTests/UserTest.php:
<?php namespace App\VoltTests; use VoltTest\Laravel\Contracts\VoltTestCase; use VoltTest\Laravel\VoltTestManager; class UserTest implements VoltTestCase { public function define(VoltTestManager $manager): void { $scenario = $manager->scenario('UserTest'); // Step 1: Home Page $scenario->step('Home Page') ->get('/') ->expectStatus(200); // Step 2: Get Registration Page to extract CSRF token $scenario->step('Get Registration Page') ->get('/register') ->expectStatus(200) ->extractCsrfToken('csrf_token'); // Extract CSRF token for registration // Step 2: User Registration $scenario->step('User Registration') ->post('/register', [ '_token' => '${csrf_token}', 'name' => 'John Doe', 'email' => 'john@example.com', 'password' => 'password', 'password_confirmation' => 'password', ] , [ 'Content-Type' => 'application/x-www-form-urlencoded' // Specify content type for form submission ]) ->expectStatus(201); } }
2. Run Your Test
Execute the performance test:
php artisan volttest:run UserTest
Or run all tests:
php artisan volttest:run
3. Direct URL Testing
Test any URL directly without creating a test class:
# Simple GET request php artisan volttest:run https://example.com --users=10 --duration=1m # POST request with data php artisan volttest:run https://api.example.com/users \ --method=POST \ --headers='{"Authorization":"Bearer token"}' \ --body='{"name":"John","email":"john@example.com"}' \ --content-type="application/json" \ --code-status=201
Creating Tests
Using Route Discovery
Generate tests with automatic route discovery:
# Include all routes php artisan volttest:make ApiTest --routes # Filter by pattern php artisan volttest:make ApiTest --routes --filter="api/*" # Filter by HTTP method php artisan volttest:make ApiTest --routes --method=GET # Include only authenticated routes php artisan volttest:make ApiTest --routes --auth # Interactive route selection php artisan volttest:make ApiTest --routes --select --filter="api/*"
Manual Test Creation
Create a test class manually:
<?php namespace App\VoltTests; use VoltTest\Laravel\Contracts\VoltTestCase; use VoltTest\Laravel\VoltTestManager; class CheckoutTest implements VoltTestCase { public function define(VoltTestManager $manager): void { $scenario = $manager->scenario('E-commerce Checkout Flow'); // Browse products $scenario->step('Browse Products') ->get('/products') ->expectStatus(200) ->extractHtml('product_id', '.product:first-child', 'data-id'); // To know how to extract the product ID, you can use a CSS selector that matches the first product element. // Reference: https://php.volt-test.com/docs/Steps#html-response // Add to cart $scenario->step('Add to Cart') ->post('/cart/add', [ '_token' => '${csrf_token}', 'product_id' => '${product_id}', 'quantity' => 1, ]) ->expectStatus(200) ->thinkTime('2s'); // Checkout $scenario->step('Checkout') ->get('/checkout') ->expectStatus(200) ->extractCsrfToken('checkout_token'); // Complete order $scenario->step('Complete Order') ->post('/checkout/complete', [ '_token' => '${checkout_token}', 'payment_method' => 'credit_card', 'shipping_address' => 'Test Address', ]) ->expectStatus(302); // Redirect after successful order } }
API Testing
Create API-focused tests:
<?php namespace App\VoltTests; use VoltTest\Laravel\Contracts\VoltTestCase; use VoltTest\Laravel\VoltTestManager; class ApiTest implements VoltTestCase { public function define(VoltTestManager $manager): void { $scenario = $manager->scenario('API Performance Test'); // Login to get token - Using headers directly in the request method $scenario->step('API Login') ->post('/api/login', [ 'email' => 'test@example.com', 'password' => 'password', ], [ 'Accept' => 'application/json' // Headers provided directly as third parameter ]) ->expectStatus(200) ->extractJson('auth_token', 'meta.token'); // Extract the authentication token from the response // Reference: https://php.volt-test.com/docs/Steps#json-response // Get user data - Using headers directly in the get method $scenario->step('Get User Data') ->get('/api/user', [ 'Authorization' => 'Bearer ${auth_token}', 'Accept' => 'application/json' // Headers provided directly in the GET method ]) ->expectStatus(200) ->extractJson('user_id', 'data.id'); // Update user - Automatic JSON conversion based on Content-Type header $scenario->step('Update User') ->put('/api/user/${user_id}', [ 'name' => 'Updated Name', 'email' => 'updated@example.com', ], [ 'Authorization' => 'Bearer ${auth_token}', 'Content-Type' => 'application/json' // This automatically converts the array to JSON ]) ->expectStatus(200); // Create new resource - Alternative way using header method $scenario->step('Create Resource') ->post('/api/resources', [ 'title' => 'New Resource', 'description' => 'Resource description' ] , [ 'Authorization' => 'Bearer ${auth_token}', 'Content-Type' => 'application/json' // This automatically converts the array to JSON ]) ->expectStatus(201); } }
Available Methods
Scenario Methods
// HTTP Methods $scenario->step('Step Name') ->get('/path') ->post('/path', $data) ->put('/path', $data) ->patch('/path', $data) ->delete('/path'); // HTTP Methods with headers parameter for automatic content type detection $scenario->step('Step Name') ->get('/path', ['Accept' => 'application/json']) ->post('/path', $data, ['Content-Type' => 'application/json']) // Array will be automatically converted to JSON ->put('/path', $data, ['Content-Type' => 'application/json']) // Array will be automatically converted to JSON ->patch('/path', $data, ['Content-Type' => 'application/json']) // Array will be automatically converted to JSON ->delete('/path', ['Accept' => 'application/json']);
Headers Data
// Headers $scenario->step('Step Name') ->header('Authorization', 'Bearer token') ->header('Accept', 'application/json'); // Content-Type headers trigger automatic data format conversion: $scenario->step('Step Name') ->post('/api/resources', ['name' => 'Product', 'price' => 19.99] , ['Content-Type'=>'application/json']); // This will automatically convert the array to JSON
Assertions
// Expectations $scenario->step('Step Name') ->expectStatus(200) ->expectStatus(201, 'custom_validation_name');
Extracting Data
// Data Extraction $scenario->step('Step Name') ->extractJson('variable_name', 'path.to.value') // Reference: https://php.volt-test.com/docs/Steps#json-response ->extractHeader('variable_name', 'Header-Name') // Reference: https://php.volt-test.com/docs/Steps#header-response ->extractHtml('variable_name', 'css-selector', 'attribute') // Reference: https://php.volt-test.com/docs/Steps#html-response ->extractRegex('variable_name', '/pattern/') // Reference: https://php.volt-test.com/docs/Steps#regular-expressions ->extractCsrfToken('csrf_token'); // Laravel-specific CSRF token extraction or u can use `extractHtml` with the CSRF token input field // Think Time $scenario->step('Step Name') ->thinkTime('2s'); // Pause between requests
Running Tests
Command Syntax
php artisan volttest:run [test] [options]
Arguments
test(optional) - The test class to run OR URL to test
Available Options
| Option | Description | Example |
|---|---|---|
--path= |
Path to search for test classes | --path=tests/Performance |
--debug |
Enable HTTP debugging | --debug |
--users= |
Number of virtual users (default: 10) | --users=50 |
--duration= |
Test duration (optional) | --duration=2m |
--stream |
Stream test output to console | --stream |
--url |
Treat the test argument as a URL for direct load testing | --url |
--method= |
HTTP method for URL testing (default: GET) | --method=POST |
--headers= |
JSON string of headers for URL testing | --headers='{"Authorization":"Bearer token"}' |
--body= |
Request body for URL testing (for POST/PUT) | --body='{"name":"John"}' |
--content-type= |
Content type for URL testing | --content-type=application/json |
--code-status= |
Expected HTTP status code for URL testing (default: 200) | --code-status=201 |
--scenario-name= |
Custom scenario name for URL testing | --scenario-name="API Load Test" |
Basic Execution
# Run all tests php artisan volttest:run # Run specific test php artisan volttest:run UserTest # Run with custom configuration php artisan volttest:run --users=20 --duration=2m --debug # Stream output in real-time php artisan volttest:run --stream
Duration Formats
The --duration option accepts various time formats:
30s- 30 seconds5m- 5 minutes2h- 2 hours90s- 90 seconds (1.5 minutes)
Header Formats
The --headers option accepts JSON format:
# Single header --headers='{"Authorization":"Bearer token"}' # Multiple headers --headers='{"Authorization":"Bearer token","Accept":"application/json","X-Custom":"value"}' # Complex headers with special characters --headers='{"User-Agent":"VoltTest/1.0","Content-Type":"application/json; charset=utf-8"}'
Body Formats
The --body option supports different formats depending on content type:
# JSON body (use with --content-type=application/json) --body='{"name":"John","email":"john@example.com","age":30}' # Form data (use with --content-type=application/x-www-form-urlencoded) --body="name=John&email=john@example.com&age=30" # Plain text --body="This is plain text content" # XML (use with --content-type=application/xml) --body='<?xml version="1.0"?><user><n>John</n><email>john@example.com</email></user>'
Advanced Options
# Custom test path php artisan volttest:run --path=tests/Performance # Multiple configuration options php artisan volttest:run UserTest \ --users=50 \ --duration=5m \ --debug \ --stream
Reports
Console Output
Test results are displayed in the console with metrics including:
- Duration and total requests
- Success rate and requests per second
- Response time statistics (min, max, avg, median, P95, P99)
Saved Reports
Reports are automatically saved as JSON files in storage/volttest/reports/:
{
"timestamp": "2025-06-23 21:22:39",
"metadata": {
"generator": "VoltTest Laravel Package"
},
"summary": {
"duration": "5.521942656s",
"total_requests": 100,
"success_rate": 48,
"requests_per_second": 18.11,
"success_requests": 48,
"failed_requests": 52
},
"response_times": {
"min": "22.361918ms",
"max": "2.061161165s",
"avg": "343.184136ms",
"median": "106.130464ms",
"p95": "1.592337048s",
"p99": "1.84969821s"
},
"metrics": {
"duration": "5.521942656s",
"totalRequests": 100,
"successRate": 48,
"requestsPerSecond": 18.11,
"successRequests": 48,
"failedRequests": 52,
"responseTime": {
"min": "22.361918ms",
"max": "2.061161165s",
"avg": "343.184136ms",
"median": "106.130464ms",
"p95": "1.592337048s",
"p99": "1.84969821s"
}
}
}
CSV Data Sources
Load dynamic test data from CSV files for more realistic and scalable performance testing scenarios.
Quick Example
- Create a CSV file at
storage/volttest/data/users.csv:
name,email,password
John Doe,user1@example.com,password123
Jane Smith,user2@example.com,password456
Bob Wilson,user3@example.com,password789
- Use the data in your test:
<?php namespace App\VoltTests; use VoltTest\Laravel\Contracts\VoltTestCase; use VoltTest\Laravel\VoltTestManager; class RegisterTest implements VoltTestCase { public function define(VoltTestManager $manager): void { // Configure CSV data source $scenario = $manager->scenario('RegisterTest') ->dataSource('users.csv'); // Step 1: Get Register Page $scenario->step('Register') ->get('/register', [ 'Content-Type' => 'application/x-www-form-urlencoded' ]) ->extractCsrfToken('token') ->expectStatus(200); // Step 2: Submit Registration $scenario->step('Register') ->post('/register', [ '_token' => '${token}', 'name' => '${name}', // From CSV column 'email' => '${email}', // From CSV column 'password' => '${password}', // From CSV column 'password_confirmation' => '${password}', ],[ 'Content-Type' => 'application/x-www-form-urlencoded' // Specify content type for form submission ]) ->expectStatus(302); // Step 3: Access Dashboard $scenario->step('Get Dashboard') ->get('/dashboard', [ 'Content-Type' => 'text/html', ]) ->expectStatus(200); } }
Distribution Modes
unique: Each virtual user gets a different CSV row (recommended for user authentication)random: Each virtual user gets a random CSV row (good for product browsing)sequential: Virtual users cycle through CSV rows in order (predictable patterns)
📖 Complete CSV Documentation
For detailed information including:
- File format requirements and validation
- All distribution modes with use cases
- Configuration options and file paths
- Troubleshooting and performance tips
- Advanced patterns and best practices
Read the complete CSV Data Source guide →
PHPUnit Integration
Run VoltTest performance tests within your PHPUnit test suite with automated server management and comprehensive performance assertions.
Configuration
To enable console reporting of performance metrics, you must register the VoltTest extension in your phpunit.xml file:
<extensions> <bootstrap class="VoltTest\Laravel\Testing\VoltTestExtension"/> </extensions>
Quick Example
<?php namespace Tests\Performance; use VoltTest\Laravel\Contracts\VoltTestCase; use VoltTest\Laravel\Testing\PerformanceTestCase; use VoltTest\Laravel\VoltTestManager; class HomePagePerformanceTest extends PerformanceTestCase { protected static bool $enableServerManagement = true; public function test_homepage_performance(): void { $testClass = new class implements VoltTestCase { public function define(VoltTestManager $manager): void { $scenario = $manager->scenario('Homepage Load Test'); $scenario->step('Load Homepage') ->get('/') ->expectStatus(200); } }; $result = $this->runVoltTest($testClass, [ 'virtual_users' => 10, 'duration' => '30s', ]); // Assert performance metrics $this->assertVTSuccessful($result, 95.0); $this->assertVTP95ResponseTime($result, 500); $this->assertVTAverageResponseTime($result, 200); } }
Key Features
- PerformanceTestCase - Base test class for PHPUnit integration
- Automatic Server Management - Built-in PHP development server lifecycle management
- Performance Assertions - Specialized assertions for response times, success rates, and throughput
- Quick Helpers - Simple methods for common load testing scenarios
Available Assertions
// Success rate assertions $this->assertVTSuccessful($result, 95.0); // >= 95% success rate $this->assertVTErrorRate($result, 5.0); // <= 5% error rate // Response time assertions $this->assertVTMinResponseTime($result, 10); // Min response time $this->assertVTMaxResponseTime($result, 2000); // Max response time $this->assertVTAverageResponseTime($result, 300); // Average response time $this->assertVTMedianResponseTime($result, 200); // Median (P50) response time $this->assertVTP95ResponseTime($result, 500); // P95 response time $this->assertVTP99ResponseTime($result, 1000); // P99 response time // Throughput assertions $this->assertVTMinimumRequests($result, 100); // Total requests >= 100 $this->assertVTMinimumRPS($result, 10.0); // Requests/sec >= 10 $this->assertVTMaximumRPS($result, 1000.0); // Requests/sec <= 1000
Quick Load Testing Helpers
// Test a single URL $result = $this->loadTestUrl('/'); $this->assertVTSuccessful($result); // Test an API endpoint $result = $this->loadTestApi('/api/users', 'POST', [ 'name' => 'John Doe', 'email' => 'john@example.com', ]); $this->assertVTSuccessful($result);
Reusing Existing VoltTest Classes
You can reuse your existing VoltTest classes in PHPUnit tests for maximum code reuse:
VoltTest Class (app/VoltTests/RegistrationTest.php):
<?php namespace App\VoltTests; use VoltTest\Laravel\Contracts\VoltTestCase; use VoltTest\Laravel\VoltTestManager; class RegistrationTest implements VoltTestCase { public function define(VoltTestManager $manager): void { $scenario = $manager->scenario('RegistrationTest') ->dataSource('registration_users.csv', 'sequential'); $scenario->step('Home')->get('/')->expectStatus(200); $scenario->step('Register')->get('/register')->extractCsrfToken('csrf_token')->expectStatus(200); $scenario->step('Submit Registration') ->post('/register', [ '_token' => '${csrf_token}', 'name' => '${name}', 'email' => '${email}', 'password' => '${password}', 'password_confirmation' => '${password}', ]) ->expectStatus(302); $scenario->step('Visit Dashboard')->get('/dashboard')->expectStatus(200); } }
PHPUnit Test (tests/Performance/RegistrationPerformanceTest.php):
<?php namespace Tests\Performance; use App\VoltTests\RegistrationTest; use VoltTest\Laravel\Testing\PerformanceTestCase; class RegistrationPerformanceTest extends PerformanceTestCase { protected static bool $enableServerManagement = true; public function test_registration_flow_performance(): void { $test = new RegistrationTest(); $result = $this->runVoltTest($test, [ 'virtual_users' => 50, 'duration' => '2m', ]); $this->assertVTSuccessful($result, 95.0); $this->assertVTP95ResponseTime($result, 1500); $this->assertVTAverageResponseTime($result, 800); } }
Benefits: Define scenarios once, run via Artisan (php artisan volttest:run RegistrationTest) or PHPUnit with assertions.
Running PHPUnit Tests
# Run all tests ./vendor/bin/phpunit # Run specific performance test ./vendor/bin/phpunit tests/Performance/HomePagePerformanceTest.php # Run performance test suite ./vendor/bin/phpunit --testsuite=Performance
📖 Complete PHPUnit Documentation
For detailed information including:
- Server management configuration
- All available assertions with examples
- Advanced test patterns and best practices
- Troubleshooting common issues
- Complete working examples
Read the complete PHPUnit Integration guide →
Testing Tips
Best Practices
- Start Small: Begin with a few virtual users and gradually increase
- Watch Server Resources: Monitor CPU, memory, and database connections
- Use Realistic Data: Incorporate CSV data sources for authentic testing
- Extract and Reuse: Extract tokens and IDs for multi-step scenarios
- Separate Concerns: Create multiple test classes for different features
- Include Think Time: Add realistic pauses between user actions
- Test API and UI: Cover both API endpoints and web interfaces
Optimizing Tests
- Increase Virtual Users Gradually: Start with 10-20 users and double until performance degrades
- Add Ramp-up Time: Allow virtual users to start gradually with
--ramp-up=30s - Use CSV Data Sources: Avoid hard-coding test data by using CSV files
- Cache CSRF Tokens: Extract tokens once and reuse where possible
- Focus on Critical Paths: Test your most important user journeys first
Troubleshooting
Common Issues
Connection Errors
- Ensure your application is running and accessible at the configured
base_url - Check firewall settings and network connectivity
- Try running with
--debugto see detailed error information
Authentication Failures
- Verify that credentials in your tests are valid
- Check session and cookie handling in your application
- Ensure proper headers are being sent (e.g.,
Authorization)
CSRF Token Issues
- Make sure your application is generating CSRF tokens
- Check the CSS selector used in
extractCsrfToken()matches your form - Try extracting the token manually with
extractHtml('token', 'meta[name="csrf-token"]', 'content')
Content Type Problems
- If JSON or HTML responses aren't parsing correctly, check the content type headers
- Use the
header('Content-Type', 'application/json')orheader('Accept', 'application/json')methods - For POST/PUT/PATCH requests with array data, adding a
Content-Type: application/jsonheader will automatically convert the array to JSON - When a response can't be properly parsed, you can use the
extractRegex()method as a fallback to extract data using regular expressions
Incorrect Parsing of Response Data
- If
extractJson()fails, check if the response is valid JSON using the debug option - For nested or complex JSON structures, use dot notation to access nested properties
- When HTML doesn't contain the expected selectors, use
extractRegex()as an alternative - If you're unsure about the response format, run with
--debugand examine the actual response
Rate Limiting
- If your API enforces rate limiting, reduce the number of virtual users or increase the think time
- Consider adding delays between requests with
thinkTime()method
Debug Commands
# Run with debug output php artisan volttest:run UserTest --debug # Reduce users for debugging php artisan volttest:run UserTest --users=1 --debug # Stream output in real-time php artisan volttest:run UserTest --stream --debug
Learn More
For more information about VoltTest and performance testing with Laravel, check out:
If you have questions, suggestions, or need help, please open an issue on our GitHub repository.
License
This Laravel package is open-sourced software licensed under the MIT license.
Changelog
Please see CHANGELOG for more information on what has changed recently.