testo/data
Testo Data provider plugin: parameterize one test into many dataset-driven runs. Supports inline tuples, named datasets, cartesian product (cross), zipped iteration, and unions across multiple sources. Install via composer require --dev testo/data.
composer require --dev testo/data
composer require --dev php-testo/testo
tests/Unit/DataTest.php) with a simple parameterized test:
use Testo\Testo;
use Testo\Data\Data;
Testo::describe('Data Provider Example', function () {
// Inline tuple example
Data::fromTuples([[1, 'one'], [2, 'two']])->it('should map numbers to words', function ($number, $word) {
$this->assertEquals($word, strval($number));
});
// Named dataset example
Data::fromArray([
'valid' => [['name' => 'John'], ['name' => 'Jane']],
'invalid' => [['name' => ''], ['name' => null]],
])->it('should handle user names', function ($userData) {
$user = new User($userData);
// Assertions...
});
});
vendor/bin/testo
Scenario: Testing a User model with varied input combinations.
testo/data to define datasets once and let the framework generate test cases.
Data::fromArray([
'valid' => [['name' => 'Alice', 'email' => 'alice@example.com']],
'invalid' => [
['name' => '', 'email' => 'invalid@example.com'],
['name' => 'Bob', 'email' => null],
],
])->it('should validate user attributes', function ($userData) {
$user = new User($userData);
$this->assertValidation($user); // Custom assertion
});
create(), assertDatabaseHas()).Use for small, ad-hoc datasets defined directly in the test.
Data::fromTuples([[1, 2, 3], [4, 5, 6]])->it('should sum arrays', function ($a, $b, $c) {
$this->assertEquals(9, $a + $b + $c);
});
Organize datasets by name (e.g., valid, invalid) for clarity and reuse.
Data::fromArray([
'valid' => [['status' => 'active'], ['status' => 'pending']],
'invalid' => [['status' => ''], ['status' => null]],
])->it('should handle status values', function ($data) {
// Test logic...
});
Generate all combinations of inputs from multiple datasets.
Data::cross([
['role' => 'admin', 'permission' => 'read'],
['role' => 'user', 'permission' => 'write'],
])->it('should validate role-permission pairs', function ($role, $permission) {
$this->assertCan($role, $permission);
});
Iterate over multiple datasets in lockstep (e.g., pairing inputs from two sources).
Data::zip(
['name' => ['Alice', 'Bob']],
['age' => [25, 30]]
)->it('should create user profiles', function ($name, $age) {
$user = new User(compact('name', 'age'));
$this->assertInstanceOf(User::class, $user);
});
Combine multiple datasets into a single test suite.
Data::union(
Data::fromTuples([[1, 2]]),
Data::fromArray(['extra' => [[3, 4]]])
)->it('should handle unioned data', function ($a, $b) {
$this->assertGreaterThan(0, $a + $b);
});
Generate test data using Laravel’s factories and pass them to datasets:
Data::fromTuples([
[User::factory()->make()->toArray()],
[User::factory()->create()->toArray()],
])->it('should handle user data', function ($userData) {
$user = User::create($userData);
$this->assertDatabaseHas('users', $userData);
});
Use RefreshDatabase with Testo by extending a custom test case:
use Illuminate\Foundation\Testing\RefreshDatabase;
use Testo\Testo;
class DatabaseTest extends Testo\TestCase {
use RefreshDatabase;
}
Testo::describe('Database Operations', function () {
Data::fromTuples([[1], [2]])->it('should insert records', function ($id) {
DB::table('users')->insert(['id' => $id, 'name' => 'Test']);
$this->assertDatabaseHas('users', ['id' => $id]);
});
});
Combine with Testo’s HTTP plugin (if available) or use Laravel’s HttpTestCase:
Data::fromArray([
'valid' => [['name' => 'John']],
'invalid' => [['name' => '']],
])->it('should handle API requests', function ($data) {
$response = $this->post('/api/users', $data);
$response->assertStatus(201);
});
Create reusable assertions for Laravel-specific logic:
function assertValidation($model) {
$this->assertTrue($model->isValid());
}
Data::fromArray() call for readability.valid_users, edge_cases).UserValidationTest.php, PermissionTest.php).@dataProvider, public function testCase($data).Data::fromTuples(...)->it('description', function ($data) { ... }).Data::sample() to test a subset:
Data::cross([...])->sample(5)->it(...);
create(), assertDatabaseHas(), etc.function createUser(array $data) {
return User::factory()->create($data);
}
beforeEach (if hybrid testing):
beforeEach(function () {
$this->user = User::factory()->create();
});
dd() or dump() inside the test to inspect data:
Data::fromArray([...])->it('debug data', function ($data) {
dump($data); // Inspect before assertions
$this->assertTrue(true); // Placeholder
});
vendor/bin/testo -v
testo.php) may not mirror Laravel’s phpunit.xml.
How can I help you explore Laravel packages today?