Generators
This document provides a detailed comparison between the available fake data generators and a migration guide for switching between them.
Available Generators
Faker (Default)
- Package: FakerPHP/Faker
- Minimum PHP: 8.2+ (project requirement)
- Install:
composer require --dev fakerphp/faker - Best for: Mature, feature-rich data generation with extensive locale support
Dummy
- Package: johnykvsky/dummygenerator
- Minimum PHP: 8.3+
- Install:
composer require --dev johnykvsky/dummygenerator - Best for: Modern PHP 8.3+ projects, native enum support, lightweight footprint
Key Differences
1. Enum Support
Faker (requires shim methods):
// Get random enum case (returns the enum object)
$status = $this->getGenerator()->enumCase(TestStatus::class);
// Get random backed enum value (returns string/int)
$statusValue = $this->getGenerator()->enumValue(TestStatus::class);DummyGenerator (native support):
// Get random enum case (native method)
$status = $this->getGenerator()->enumCase(TestStatus::class);
// Get random backed enum value
$statusValue = $this->getGenerator()->enumValue(TestStatus::class);2. Locale Support
Faker:
- Full locale support with locale-specific data
- 50+ locales available
- Example:
CakeGeneratorFactory::create('fr_FR')
DummyGenerator:
- Limited locale support
- Parameter is accepted for interface compatibility but may not affect output
- Focuses on generic data generation
3. Method Compatibility
Most methods work identically across both generators. However, some methods are shimmed for compatibility:
| Method | Faker | DummyGenerator | Notes |
|---|---|---|---|
uuid() | Native | Mapped to uuid4() | Both generate valid UUIDs |
realText() | Native | Mapped to text() | Same behavior |
randomAscii() | Native | Shimmed | Returns ASCII character (33-126) |
enumCase() | Shimmed | Native | Recommended for enums |
enumValue() | Shimmed | Shimmed | Works on both |
4. Seeding Behavior
Both generators support seeding for reproducible test data. By default, factories are seeded with 1234. You can configure a different seed globally:
Configure::write('FixtureFactories.seed', 9999);Faker:
$generator->seed(1234);DummyGenerator:
$generator->seed(1234); // Uses XoshiroRandomizer internally5. Performance
Faker:
- Mature and well-tested
- Larger footprint
- More features and providers
DummyGenerator:
- Modern PHP 8.3+ optimizations
- Leaner codebase
- Faster for basic operations
Switching Generators
Configuration
Set the generator type in your tests/bootstrap.php or test configuration:
use Cake\Core\Configure;
// Use Faker (default)
Configure::write('FixtureFactories.generatorType', 'faker');
// Use DummyGenerator
Configure::write('FixtureFactories.generatorType', 'dummy');Or set it per-factory:
$article = ArticleFactory::make()
->setGenerator('dummy')
->getEntity();Note: By default,
setGenerator()changes the generator globally. EnableFixtureFactories.instanceLevelGeneratorto limit it to the current instance. See Fixture Factories.
Migration Guide: Faker → DummyGenerator
Step 1: Install DummyGenerator
composer require --dev johnykvsky/dummygeneratorStep 2: Update Configuration
// In tests/bootstrap.php
Configure::write('FixtureFactories.generatorType', 'dummy');Step 3: Test Your Factories
Run your test suite to ensure compatibility:
vendor/bin/phpunitStep 4: (Optional) Remove Faker
If you no longer need Faker:
composer remove --dev fakerphp/fakerMigration Guide: DummyGenerator → Faker
Step 1: Install Faker
composer require --dev fakerphp/fakerStep 2: Update Configuration
// In tests/bootstrap.php
Configure::write('FixtureFactories.generatorType', 'faker');Step 3: Update Enum Methods (if using)
enumCase() and enumValue() work on both, so no changes needed unless you're using DummyGenerator-specific features.
Step 4: Adjust for Locale (if needed)
Take advantage of Faker's locale support:
$generator = CakeGeneratorFactory::create('fr_FR');Step 5: Test Your Factories
Run your test suite:
vendor/bin/phpunitCommon Pitfalls
1. PHP Version Requirements
Problem: DummyGenerator requires PHP 8.3+
Solution: Check your PHP version before switching:
php -v2. Locale-Specific Data
Problem: DummyGenerator doesn't support locale-specific data like Faker
Solution: If you need locale-specific data, stick with Faker or implement custom data providers
3. Unique Values
Problem: Different retry mechanisms for unique values
Solution: Both support unique() modifier, but DummyGenerator has a custom retry mechanism (10,000 attempts vs Faker's default)
// Works on both
$generator->unique()->email();Best Practices
1. Keep Factory Code Generator-Agnostic
Write factory code that works with both generators:
// Good - works with both
'email' => $this->getGenerator()->email(),
'name' => $this->getGenerator()->name(),
'status' => $this->getGenerator()->enumCase(TestStatus::class),
// Avoid generator-specific methods unless necessary2. Use Configuration for Switching
Don't hardcode generator selection in factories:
// Good - use configuration
Configure::write('FixtureFactories.generatorType', 'dummy');
// Good - per-factory override
ArticleFactory::make()->setGenerator('dummy')->getEntity();
// Good - set global default explicitly
BaseFactory::setDefaultGenerator('dummy');Tip: Enable
FixtureFactories.instanceLevelGeneratorso thatsetGenerator()only affects the current factory instance. See Fixture Factories.
3. Test with Both Generators (Optional)
If your library supports multiple PHP versions, test with both:
# .github/workflows/ci.yml
matrix:
php: ['8.2', '8.3', '8.4']
generator: ['faker', 'dummy']
exclude:
- php: '8.2'
generator: 'dummy'4. Seed for Reproducible Tests
Factories are seeded with 1234 by default for reproducible data. You can configure a different seed globally:
// In tests/bootstrap.php or config/app.php
Configure::write('FixtureFactories.seed', 9999);See config/app.example.php in this plugin for all available configuration options.
Feature Matrix
| Feature | Faker | DummyGenerator |
|---|---|---|
| Basic data types | ✅ | ✅ |
| Text generation | ✅ | ✅ |
| Date/time | ✅ | ✅ |
| Internet (email, URL) | ✅ | ✅ |
| Person (name, title) | ✅ | ✅ |
| Address | ✅ | ✅ |
| Phone numbers | ✅ | ✅ |
| Company | ✅ | ✅ |
| UUID | ✅ | ✅ |
| Colors | ✅ | ✅ |
| Credit cards | ✅ | ✅ |
| Barcodes (EAN, ISBN) | ✅ | ✅ |
| Locale support | ✅ Full | ⚠️ Limited |
| Native enum support | ⚠️ Shimmed | ✅ Native |
unique() modifier | ✅ | ✅ |
optional() modifier | ✅ | ✅ |
| Seeding | ✅ | ✅ |
| Minimum PHP version | 8.2+ | 8.3+ |
Performance Comparison
While both generators are fast enough for testing purposes, here's a general comparison:
Faker:
- Mature codebase with extensive providers
- ~5-10ms average per factory creation
- Larger memory footprint
DummyGenerator:
- Modern PHP 8.3+ optimizations
- ~3-7ms average per factory creation
- Smaller memory footprint
- Native enum handling is faster
Note: Performance differences are typically negligible for test suites. Choose based on features and PHP version requirements rather than performance.
Troubleshooting
"Class not found" errors
Faker not found:
Faker library is not installed. Please install it using: `composer require --dev fakerphp/faker`DummyGenerator not found:
DummyGenerator library is not installed. Please install it using: `composer require --dev johnykvsky/dummygenerator`Solution: Install the required package.
Method not found
Problem: A method works with one generator but not the other
Solution: Check the compatibility table above. Most methods are shimmed, but some advanced features may differ.
Additional Resources
FAQ
Which generator should I use?
- Use Faker if you need extensive locale support or need to support PHP < 8.3
- Use DummyGenerator if you're on PHP 8.3+ and want a modern, lean solution with native enum support
Can I use both generators in the same project?
Yes! You can configure different generators per-factory or switch globally. However, it's recommended to use one consistently for maintainability.
Will my existing factories break if I switch?
Most likely not. The plugin provides compatibility shims for common methods. However, test your factories after switching.
How do I contribute new methods?
Add them to GeneratorInterface and implement in both FakerAdapter and DummyGeneratorAdapter, ensuring compatibility across both generators.
Can I create a custom generator?
Yes! Implement GeneratorInterface and register it:
use CakephpFixtureFactories\Generator\CakeGeneratorFactory;
CakeGeneratorFactory::registerAdapter('custom', MyCustomAdapter::class);
Configure::write('FixtureFactories.generatorType', 'custom');