☁️VoltTest Cloud closed beta is now openJoin the waitlist
Skip to main content

Creating Tests

Test Structure

Every VoltTest test class implements VoltTestCase and defines scenarios in the define() method:

<?php

namespace App\VoltTests;

use VoltTest\Laravel\Contracts\VoltTestCase;
use VoltTest\Laravel\VoltTestManager;

class CheckoutTest implements VoltTestCase
{
public function define(VoltTestManager $manager): void
{
$manager->target('http://localhost:8000');

$scenario = $manager->scenario('Checkout Flow');

$scenario->step('Browse Products')
->get('/products')
->expectStatus(200);

$scenario->step('Add to Cart')
->post('/cart', ['product_id' => 1, 'quantity' => 2], [
'Content-Type' => 'application/json',
])
->expectStatus(200);
}
}

Scenarios

Create scenarios through the $manager->scenario() method. Each scenario represents a user flow.

Multiple Scenarios

Use weights to control how virtual users are distributed across scenarios:

public function define(VoltTestManager $manager): void
{
$manager->target('http://localhost:8000');

$browse = $manager->scenario('Browse Only');
$browse->weight(70);
$browse->step('Home')->get('/')->expectStatus(200);
$browse->step('Products')->get('/products')->expectStatus(200);

$purchase = $manager->scenario('Purchase Flow');
$purchase->weight(30);
$purchase->step('Home')->get('/')->expectStatus(200);
$purchase->step('Checkout')->post('/checkout', [...])->expectStatus(200);
}

70% of virtual users will browse, 30% will purchase.

Think Time

Add delays between steps to simulate real user behavior:

$scenario->step('View Product')
->get('/products/1')
->expectStatus(200)
->thinkTime('2s');

$scenario->step('Add to Cart')
->post('/cart', ['product_id' => 1])
->expectStatus(200);

Steps

Each step represents an HTTP request. Create steps with step() then chain the HTTP method:

$scenario->step('Step Name')
->get('/path')
->expectStatus(200);

HTTP Methods

$scenario->step('Get')->get('/users');
$scenario->step('Create')->post('/users', $data, $headers);
$scenario->step('Update')->put('/users/1', $data, $headers);
$scenario->step('Patch')->patch('/users/1', $data, $headers);
$scenario->step('Delete')->delete('/users/1');

Headers

Add headers inline or with the header() method:

// Inline headers (second/third parameter)
$scenario->step('Create')
->post('/api/users', ['name' => 'John'], [
'Content-Type' => 'application/json',
'Accept' => 'application/json',
]);

// Chained headers
$scenario->step('Get Profile')
->get('/api/profile')
->header('Authorization', 'Bearer ${token}')
->header('Accept', 'application/json');

Auto-JSON Encoding

When you pass an array as the request body with a JSON Content-Type header, the package automatically encodes it to JSON:

$scenario->step('Create User')
->post('/api/users', ['name' => 'John', 'email' => 'john@example.com'], [
'Content-Type' => 'application/json',
]);

Base URL

By default, relative paths (e.g., /login) are prefixed with the configured base_url (http://localhost:8000). Full URLs are used as-is.

$scenario->step('Local')->get('/api/health');
// → http://localhost:8000/api/health

$scenario->step('External')->get('https://api.example.com/health');
// → https://api.example.com/health

Configure in .env:

VOLTTEST_BASE_URL=http://localhost:8000

Route Discovery

Generate test scaffolds from your existing Laravel routes:

php artisan volttest:make ApiTest --routes --filter=api/*

This creates a test class with steps for each matching route:

class ApiTest implements VoltTestCase
{
public function define(VoltTestManager $manager): void
{
$manager->target('http://localhost:8000');

$scenario = $manager->scenario('API Routes');

$scenario->step('GET /api/users')
->get('/api/users')
->expectStatus(200);

$scenario->step('POST /api/users')
->post('/api/users')
->expectStatus(200);

// ... more routes
}
}

Filtering Routes

# By URI pattern
php artisan volttest:make Test --routes --filter=api/v1/*

# By HTTP method
php artisan volttest:make Test --routes --method=GET

# Only authenticated routes
php artisan volttest:make Test --routes --auth

# Interactive selection
php artisan volttest:make Test --routes --select

The Laravel package automatically enables cookie handling for all scenarios. This means Laravel session cookies, CSRF tokens, and other cookies are preserved across steps — matching how a real browser works.