Download the PHP package binarysolutions/test-data-blueprints without Composer
On this page you can find all versions of the php package binarysolutions/test-data-blueprints. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download binarysolutions/test-data-blueprints
More information about binarysolutions/test-data-blueprints
Files in binarysolutions/test-data-blueprints
Package test-data-blueprints
Short Description Laravel package for reusable scenario-based test datasets beyond factories and seeders.
License MIT
Informations about the package test-data-blueprints
Laravel Test Data Blueprints
Reusable, composable, scenario-based test datasets for Laravel.
Factories solve object construction. Seeders solve bulk population.
Neither solves the problem of named, reusable domain scenarios — the
"company with an active subscription and 3 admin users in the onboarding state"
you need to set up consistently across dozens of feature tests.
Blueprints fill that gap.
Contents
- Installation
- Core concepts
- Defining a blueprint
- Steps: create, make, tap
- Ref tokens
- Composition with
->use() - Time travel with
->at() - Snapshots and caching
- ⚠ Test isolation and RefreshDatabase
- Using in tests (PHPUnit)
- Using in tests (Pest)
- Using in local seeders
- Artisan commands
- Configuration
- Troubleshooting
Installation
⚠ Always install with
--dev. This package must not be present in production.
Optionally publish the config file:
Blueprint files live in database/blueprints/ by default (alongside migrations, factories, and seeders — all database-layer concerns in one place). Create the directory:
Core concepts
| Concept | What it is |
|---|---|
| Blueprint | A named, parameterisable scenario definition stored as a PHP file in database/blueprints/. |
| Step | One unit of work inside a blueprint: ->create(), ->make(), or ->tap(). |
| Ref | A named value produced by a step and stored in the BlueprintResult. Later steps (and tests) access refs by name. |
| @ref token | A string like '@company' or '@users[0].id' that resolves to a previously stored ref at runtime. |
| Composition | ->use('other-blueprint') imports all refs from another blueprint before this blueprint's own steps run. |
| Snapshot | In-memory caching of a BlueprintResult for the duration of a test process. Safe only for in-memory blueprints. |
Defining a blueprint
Generate a stub:
A blueprint file returns a Blueprint instance:
Blueprint names are arbitrary strings. Use colons, hyphens, or slashes for namespacing:
Steps: create, make, tap
->create() — persist to the database
Calls factory->create(). Use this in feature tests where you need real database rows.
->make() — build without persisting
Calls factory->make(). Use this in unit tests where you only need model instances and do not want a database round-trip. Safe to combine with ->snapshot().
->tap() — arbitrary callable
Use ->tap() for computed values, pivot records, plain objects, or anything that does not fit a factory call.
Ref tokens
Any step can reference the output of a previous step using @refName:
Supported token syntax:
| Token | Resolves to |
|---|---|
@company |
The entire value stored under company |
@company.id |
->id on an object, or ['id'] on an array |
@users[0] |
First element of the users collection/array |
@users[0].email |
email property of the first user |
Composition with ->use()
->use() runs the named blueprint first and merges all its refs into the current result. If the dependency and the current blueprint define the same ref key, the dependency's value wins (existing refs are not overwritten).
Multiple ->use() calls are supported and resolved in order.
Time travel with ->at()
->at() wraps the entire blueprint run in Carbon::setTestNow() and restores the previous value (including null) in a finally block, so it never leaks into the surrounding test.
Snapshots and caching
When ->snapshot() is set, the SnapshotManager caches the BlueprintResult in memory keyed by name + params. Subsequent calls with the same name and params return the same instance without re-running steps.
⚠ Test isolation and RefreshDatabase
Do not use ->snapshot() on blueprints that call ->create() when your test suite uses RefreshDatabase.
Here is why:
- Test A runs →
$this->blueprint('saas-company')→ creates rows →SnapshotManagercaches theBlueprintResultcontaining Eloquent model instances pointing to ids1, 2, 3. RefreshDatabaserolls back the transaction → rows are gone from the database.- Test B runs →
$this->blueprint('saas-company')→SnapshotManagerreturns the cached result → the models still point to ids1, 2, 3→ those rows no longer exist.
The UsesBlueprints trait guards against this by calling clearBlueprintSnapshots() automatically before each test (via PHPUnit's setUp<TraitName>() convention). This means:
- Each test gets a fresh blueprint run.
- Models created in one test's transaction are never shared with another test.
- Blueprints using
->create()work correctly alongsideRefreshDatabase.
If all your blueprints use only ->make() or ->tap() (no DB writes), you can opt out of the auto-clear for a small performance gain:
Using in tests (PHPUnit)
Using in tests (Pest)
In tests/Pest.php:
In a test file:
Using in local seeders
Blueprints are plain PHP — you can call the engine directly from a DatabaseSeeder to populate your local environment with realistic scenario data:
Artisan commands
All commands are only registered in local and testing environments.
make:blueprint
Generates a stub in database/blueprints/.
blueprints:list
Lists all discovered blueprints and their class types.
blueprints:run
Runs a blueprint against the current database connection and displays its refs.
Useful for quickly inspecting a blueprint or seeding a local environment.
Configuration
You can register additional paths to load blueprints from packages or other modules:
Troubleshooting
Unknown blueprint 'my-blueprint'. Available: ...
The blueprint name in the error is what the file returns (Blueprint::define('...')), not the filename. Check that the name in define() matches what you are calling. Run blueprints:list to see all discovered names.
Two blueprints have the same name
Each *.php file in a scanned path must return a blueprint with a unique name. If two files return the same name, the last one loaded (by filesystem sort order) silently wins. Rename one of them.
Tests pass individually but fail when the full suite runs
This is almost always snapshot contamination. Make sure you are using RefreshDatabase alongside UsesBlueprints, and that the blueprints involved do not use ->snapshot(). The trait's auto-clear (setUpUsesBlueprints) clears the cache before each test, but only if $autoClearBlueprintSnapshots is true (the default).
->at() is not restoring Carbon after a test
->at() restores inside a finally block, so it always restores even on exception. If Carbon's test now is set outside the blueprint (e.g. by TestCase::setUp), the blueprint will restore to that external value, not null.
Commands are not available
Commands are registered only when app()->environment('local', 'testing') is true. If you are running in a custom environment (e.g. APP_ENV=development), either add it to the service provider's environment list or set APP_ENV=local locally.