lhabbich / drupal-mock-data-seeder
Drupal development module to generate realistic nested content trees for testing.
Package info
github.com/habbichelotfi/drupal-mock-data-seeder
Type:drupal-module
pkg:composer/lhabbich/drupal-mock-data-seeder
Requires
- php: >=8.1
- drupal/core: ^10.3 || ^11
- fakerphp/faker: ^1.24
Requires (Dev)
- drupal/coder: ^8.3
- phpstan/phpstan: ^1.12
- phpunit/phpunit: ^10.5
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-06 18:45:14 UTC
README
Development module for generating realistic Drupal content trees for local development, UI testing, and load testing. It can create or reuse:
- nodes;
- nested Paragraphs, when the Paragraphs module is available;
- taxonomy references and optional terms;
- media references and optional remote-video media.
This module is intended for non-production environments. It is disabled by default and includes environment, count, and rollback safeguards.
Requirements
- PHP 8.1 or newer according to
composer.json; - Drupal 10.3+ or Drupal 11;
- Composer;
- Drush for the command-line examples;
- optional: Paragraphs and Media modules for those entity types.
The current committed composer.lock resolves Drupal 11.4.6, which requires
PHP 8.3 or newer. Use PHP 8.3+ with the lock file, or regenerate the lock file
under PHP 8.1/8.2 with dependency versions compatible with that runtime.
Installation
From the Drupal project root containing this package:
composer install --no-interaction --prefer-dist drush en drupal_mock_data_seeder -y drush cset drupal_mock_data_seeder.settings enabled 1 -y drush cr
Review the generated configuration before enabling the module in any shared
environment. The module's default configuration is in
config/install/drupal_mock_data_seeder.settings.yml.
Quick start
Configure an existing content type and enable seeding with the setup assistant:
drush mock:setup
It prompts for an existing type. For scripts, supply the machine name explicitly:
drush mock:setup --profile=default --bundle=page
On an empty site, explicitly request creation of a minimal content type:
drush mock:setup --bundle=article --create-bundle=1
This creates the content type without adding custom fields or a body field. Add those through Drupal's field administration as needed. Setup updates only the selected existing profile's bundle and enables the seeder. It respects the environment block list and does not generate content.
Run a dry-run first. It validates the profile and bundle without saving entities:
drush mock:seed --profile=default --dry-run=1
Generate 20 nodes using the page bundle, three levels of nesting, and French
fake data:
drush mock:seed \ --profile=default \ --bundle=page \ --count=20 \ --depth=3 \ --locale=fr_FR
Reproducible runs
Pass an integer seed to make Faker and PHP random choices repeatable:
drush mock:seed --profile=default --count=20 --seed=4242
The seed is included in the run result and stored run metadata.
Custom fields
Empty configurable fields on nodes and Paragraphs are now filled for these types:
string, string_long, email, telephone, boolean, integer, decimal,
float, link, datetime, timestamp, list_string, list_integer, and
list_float. One item is generated per field. String length, numeric bounds,
decimal precision, static allowed values, date storage format, and internal-only
links are taken into account. Existing values and base, computed, and read-only
fields are preserved.
Dynamic allowed-value callbacks and unsupported field types are skipped. The existing specialized logic still handles body text, Paragraph title/text fields, taxonomy and media references. Arbitrary formatted-text fields, images, files, and custom module constraints are not automatically handled by this generator.
JSON reports
Use --json=1 for scripts and CI integrations. The report includes the run ID,
profile, bundle, requested count, depth, locale, seed, duration, and entity
statistics:
drush mock:seed --profile=default --count=10 --json=1
Paragraph field configuration and warnings
All empty writable Paragraph reference fields are populated, including multiple
fields on the same node. Generation uses installed Paragraph types permitted by
each field's target_bundles and negate settings, and respects field cardinality.
An absent or null target list allows all installed types; an empty list allows
none (or all when negated). Custom selection plugins may impose additional rules
that this configuration-based selection does not evaluate.
The profile's paragraph_types list further restricts those types. An empty or
omitted profile list enables automatic discovery; new installations use an empty
list by default. Existing installations keep their configured list. To use
automatic discovery on an existing site, set this in its active seeder config:
profiles: default: paragraph_types: []
This fragment shows only the setting to change; preserve the rest of the config.
An explicit list with no allowed match produces a warning and skips the field.
Root fields use paragraphs_per_node, capped by their cardinality. Required fields
receive at least one item when possible. Nested fields receive one child when
required; optional nested fields have a 35% chance of receiving one. --depth
always limits nesting, including required fields and self-referencing types.
The run report includes a deduplicated warnings array, also displayed in Drush.
It identifies empty required configurable fields by entity type, bundle and field
name, including fields left empty at the depth limit. Check a simulation with:
drush mock:seed --count=5 --depth=3 --dry-run=1 --json=1
These warnings are advisory, not complete Drupal entity validation, and do not prevent a real run. A dry run saves neither entities nor run metadata; its entity statistics remain zero. Because dry runs do not create missing taxonomy or media, required references to those entities may be reported empty even when a real run could create them.
Diagnostics
Check configuration and runtime prerequisites without creating entities:
drush mock:doctor --profile=default
The diagnostic checks include:
- whether the seeder is enabled;
- whether the requested profile exists;
- whether the target node bundle exists;
- whether the current environment is blocked by safeguards;
- whether the system temporary directory is writable.
For automation, request JSON output:
drush mock:doctor --profile=default --json=1
Rollback
Each non-dry run stores the IDs of entities it created. Roll back a specific run with its reported ID:
drush mock:reset --run-id=20260901_102030_abcd1234
The run is recorded before generation and its entity IDs are saved after each
successful entity save, including related entities created before their parent.
If generation throws an error, the run is marked failed and the error includes
the exact reset command. Cleanup is explicit: run that command to delete the
recorded entities. Reused entities are not recorded or deleted.
A process interruption leaves the recorded run available for reset. This is a recovery journal, not an atomic transaction: a hard stop between an entity save and its journal update, or a failure inside an entity save hook, may leave an unrecorded entity. Successful reset also clears the last-run pointer when it points to the deleted run.
If the configured safeguard requires a run ID, omitting it fails safely. To roll back the last stored run explicitly:
drush mock:reset --force=1
Safety configuration
The module is disabled by default. Relevant settings are:
enabled: explicitly enables seeding;safeguards.max_count: maximum root nodes per run;safeguards.blocked_envs: environment values that block execution;safeguards.env_var_names: environment variables inspected;safeguards.require_run_id_for_reset: requires an explicit rollback ID.
Use --force=1 only when you understand the consequences:
drush mock:seed --profile=default --count=500 --force=1 drush mock:reset --force=1
Development and quality checks
Install development dependencies and run the complete local quality suite:
composer install composer qa
Individual checks:
composer test:smoke
composer lint
composer analyze
composer test
The service tests can run without a bootstrapped Drupal site:
vendor/bin/phpunit tests/src/Unit
The GitHub Actions workflow runs the smoke test, Drupal coding standards, and PHPStan analysis. Kernel tests require a correctly configured Drupal test environment.
Contributing
See CONTRIBUTING.md before opening a pull request. Behavior changes should
include tests and corresponding documentation updates. User-facing changes
should be recorded in CHANGELOG.md.
License
This project is released under the MIT License. See LICENSE.