Skip to content

Commit

Permalink
feat(faker): load faker seed from env var
Browse files Browse the repository at this point in the history
  • Loading branch information
nikophil committed Feb 5, 2025
1 parent 77ae53c commit dd8c733
Show file tree
Hide file tree
Showing 14 changed files with 293 additions and 37 deletions.
10 changes: 9 additions & 1 deletion bin/console
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,13 @@ use Zenstruck\Foundry\Tests\Fixture\TestKernel;

require_once __DIR__ . '/../tests/bootstrap.php';

$application = new Application(new TestKernel('test', true));
foreach ($argv ?? [] as $i => $arg) {
if (($arg === '--env' || $arg === '-e') && isset($argv[$i + 1])) {
$_ENV['APP_ENV'] = $argv[$i + 1];
break;
}
}

$application = new Application(new TestKernel($_ENV['APP_ENV'], true));

$application->run();
1 change: 1 addition & 0 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
service('.zenstruck_foundry.story_registry'),
service('.zenstruck_foundry.persistence_manager')->nullOnInvalid(),
service('event_dispatcher'),
'%env(default:zenstruck_foundry.faker.seed:int:FOUNDRY_FAKER_SEED)%',
])
->public()
;
Expand Down
15 changes: 15 additions & 0 deletions src/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ final class Configuration
/** @var \Closure():self|self|null */
private static \Closure|self|null $instance = null;

private static int|null $fakerSeed = null;

/**
* @phpstan-param InstantiatorCallable $instantiator
*/
Expand All @@ -53,10 +55,23 @@ public function __construct(
public readonly StoryRegistry $stories,
private readonly ?PersistenceManager $persistence = null,
private readonly ?EventDispatcherInterface $eventDispatcher = null,
int|null $forcedFakerSeed = null,
) {
$this->faker->seed(self::fakerSeed($forcedFakerSeed));

$this->instantiator = $instantiator;
}

public static function fakerSeed(int|null $forcedFakerSeed = null): int
{
return self::$fakerSeed ??= ($forcedFakerSeed ?? random_int(0, 1000000));
}

public static function resetFakerSeed(): void
{
self::$fakerSeed = null;
}

/**
* @throws PersistenceNotAvailable
*/
Expand Down
1 change: 1 addition & 0 deletions src/Test/UnitTestConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public static function build(): Configuration
$faker,
self::$instantiator ?? Instantiator::withConstructor(),
new StoryRegistry([]),
forcedFakerSeed: $_SERVER['FOUNDRY_FAKER_SEED'] ?? $_ENV['FOUNDRY_FAKER_SEED'] ?? (getenv('FOUNDRY_FAKER_SEED') ?: null)
);
}
}
6 changes: 2 additions & 4 deletions src/ZenstruckFoundryBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public function configure(DefinitionConfigurator $definition): void
->defaultNull()
->end()
->scalarNode('seed')
->setDeprecated('zenstruck/foundry', '2.4', 'The "faker.seed" configuration is deprecated and will be removed in 3.0.')
->setDeprecated('zenstruck/foundry', '2.4', 'The "faker.seed" configuration is deprecated and will be removed in 3.0. Use environment variable "FOUNDRY_FAKER_SEED" instead.')
->info('Random number generator seed to produce the same fake values every run.')
->example(1234)
->defaultNull()
Expand Down Expand Up @@ -405,8 +405,6 @@ private function configureFaker(array $config, ContainerBuilder $container): voi
$definition->addArgument($config['locale']);
}

if ($config['seed']) {
$definition->addMethodCall('seed', [$config['seed']]);
}
$container->setParameter('zenstruck_foundry.faker.seed', $config['seed']);
}
}
2 changes: 2 additions & 0 deletions tests/Fixture/config/faker_seed_env_var.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
parameters:
env(FOUNDRY_FAKER_SEED): 1234
File renamed without changes.
32 changes: 0 additions & 32 deletions tests/Integration/BundleTest.php

This file was deleted.

38 changes: 38 additions & 0 deletions tests/Integration/Faker/FakerSeedAutomaticallySetKernelTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Zenstruck\Foundry\Tests\Integration\Faker;

use PHPUnit\Framework\Attributes\Depends;
use PHPUnit\Framework\Attributes\RequiresPhpunit;
use PHPUnit\Framework\Attributes\Test;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Foundry\Configuration;
use Zenstruck\Foundry\Test\Factories;
use Zenstruck\Foundry\Test\ResetDatabase;

/**
* @author Nicolas PHILIPPE <[email protected]>
* @requires PHPUnit >=11.0
*/
#[RequiresPhpunit('>=11.0')]
final class FakerSeedAutomaticallySetKernelTest extends KernelTestCase
{
use Factories, ResetDatabase, FakerTestTrait;

#[Test]
public function faker_seed_does_not_change(): void
{
self::$currentSeed = Configuration::fakerSeed();

self::assertSame(self::$currentSeed, Configuration::fakerSeed());
}

#[Test]
#[Depends('faker_seed_does_not_change')]
public function faker_seed_does_not_change_between_tests(): void
{
self::assertSame(self::$currentSeed, Configuration::fakerSeed());
}
}
37 changes: 37 additions & 0 deletions tests/Integration/Faker/FakerSeedAutomaticallySetUnitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Zenstruck\Foundry\Tests\Integration\Faker;

use PHPUnit\Framework\Attributes\Depends;
use PHPUnit\Framework\Attributes\RequiresPhpunit;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Zenstruck\Foundry\Configuration;
use Zenstruck\Foundry\Test\Factories;

/**
* @author Nicolas PHILIPPE <[email protected]>
* @requires PHPUnit >=11.0
*/
#[RequiresPhpunit('>=11.0')]
final class FakerSeedAutomaticallySetUnitTest extends TestCase
{
use Factories, FakerTestTrait;

#[Test]
public function faker_seed_does_not_change(): void
{
self::$currentSeed = Configuration::fakerSeed();

self::assertSame(self::$currentSeed, Configuration::fakerSeed());
}

#[Test]
#[Depends('faker_seed_does_not_change')]
public function faker_seed_does_not_change_between_tests(): void
{
self::assertSame(self::$currentSeed, Configuration::fakerSeed());
}
}
48 changes: 48 additions & 0 deletions tests/Integration/Faker/FakerSeedSetFromEnvVarKernelTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace Zenstruck\Foundry\Tests\Integration\Faker;

use PHPUnit\Framework\Attributes\Depends;
use PHPUnit\Framework\Attributes\RequiresPhpunit;
use PHPUnit\Framework\Attributes\Test;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Foundry\Configuration;
use Zenstruck\Foundry\Test\Factories;
use Zenstruck\Foundry\Test\ResetDatabase;
use Zenstruck\Foundry\Tests\Fixture\Factories\Entity\Address\AddressFactory;

/**
* @author Nicolas PHILIPPE <[email protected]>
* @requires PHPUnit >=11.0
*/
#[RequiresPhpunit('>=11.0')]
final class FakerSeedSetFromEnvVarKernelTest extends KernelTestCase
{
use Factories, ResetDatabase, FakerTestTrait;

#[Test]
public function faker_seed_can_be_set_by_environment_variable(): void
{
// let's fake, we're starting from a fresh kernel
$this->tearDown();
Configuration::shutdown();
Configuration::resetFakerSeed();

self::bootKernel(['environment' => 'faker_seed_env_var']);

self::assertSame(1234, Configuration::fakerSeed());

self::assertSame('Baileyshire', AddressFactory::createOne()->getCity());
}

#[Test]
#[Depends('faker_seed_can_be_set_by_environment_variable')]
public function faker_seed_is_already_set(): void
{
self::assertSame(1234, Configuration::fakerSeed());

self::assertSame('Baileyshire', AddressFactory::createOne()->getCity());
}
}
55 changes: 55 additions & 0 deletions tests/Integration/Faker/FakerSeedSetFromEnvVarUnitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace Zenstruck\Foundry\Tests\Integration\Faker;

use PHPUnit\Framework\Attributes\AfterClass;
use PHPUnit\Framework\Attributes\Before;
use PHPUnit\Framework\Attributes\BeforeClass;
use PHPUnit\Framework\Attributes\Depends;
use PHPUnit\Framework\Attributes\RequiresPhpunit;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Zenstruck\Foundry\Configuration;
use Zenstruck\Foundry\Test\Factories;
use Zenstruck\Foundry\Tests\Fixture\Factories\Entity\Address\AddressFactory;

/**
* @author Nicolas PHILIPPE <[email protected]>
* @requires PHPUnit >=11.0
*/
#[RequiresPhpunit('>=11.0')]
final class FakerSeedSetFromEnvVarUnitTest extends TestCase
{
use Factories, FakerTestTrait;

#[Before(10)]
public static function __setEnv(): void
{
$_ENV['FOUNDRY_FAKER_SEED'] = $_SERVER['FOUNDRY_FAKER_SEED'] = '1234';
}

#[Test]
public function faker_seed_is_set_from_env_var(): void
{
self::assertSame(1234, Configuration::fakerSeed());

self::assertSame('Baileyshire', AddressFactory::createOne()->getCity());
}

#[Test]
#[Depends('faker_seed_is_set_from_env_var')]
public function faker_seed_does_not_change(): void
{
self::assertSame(1234, Configuration::fakerSeed());

self::assertSame('Baileyshire', AddressFactory::createOne()->getCity());
}

#[AfterClass(-9)] // @phpstan-ignore argument.type (negative priority should be allowed)
public static function __resetFakerSeedEnv(): void
{
unset($_ENV['FOUNDRY_FAKER_SEED'], $_SERVER['FOUNDRY_FAKER_SEED']);
}
}
54 changes: 54 additions & 0 deletions tests/Integration/Faker/FakerSeedSetFromLegacyConfigKernelTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace Zenstruck\Foundry\Tests\Integration\Faker;

use PHPUnit\Framework\Attributes\Depends;
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
use PHPUnit\Framework\Attributes\RequiresPhpunit;
use PHPUnit\Framework\Attributes\Test;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Foundry\Configuration;
use Zenstruck\Foundry\Test\Factories;
use Zenstruck\Foundry\Test\ResetDatabase;
use Zenstruck\Foundry\Tests\Fixture\Factories\Entity\Address\AddressFactory;

/**
* @author Nicolas PHILIPPE <[email protected]>
* @requires PHPUnit >=11.0
*/
#[RequiresPhpunit('>=11.0')]
final class FakerSeedSetFromLegacyConfigKernelTest extends KernelTestCase
{
use Factories, ResetDatabase, FakerTestTrait;

#[Test]
#[IgnoreDeprecations]
public function test_faker_seed_by_configuration_is_deprecated(): void
{
// let's fake, we're starting from a fresh kernel
$this->tearDown();
Configuration::shutdown();
Configuration::resetFakerSeed();

self::bootKernel(['environment' => 'faker_seed_legacy_config']);

self::expectUserDeprecationMessageMatches(
'/The "faker.seed" configuration is deprecated and will be removed in 3.0/'
);

self::assertSame(1234, Configuration::fakerSeed());

self::assertSame('Baileyshire', AddressFactory::createOne()->getCity());
}

#[Test]
#[Depends('test_faker_seed_by_configuration_is_deprecated')]
public function faker_seed_is_already_set(): void
{
self::assertSame(1234, Configuration::fakerSeed());

self::assertSame('Baileyshire', AddressFactory::createOne()->getCity());
}
}
31 changes: 31 additions & 0 deletions tests/Integration/Faker/FakerTestTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace Zenstruck\Foundry\Tests\Integration\Faker;

use PHPUnit\Framework\Attributes\AfterClass;
use PHPUnit\Framework\Attributes\BeforeClass;
use Zenstruck\Foundry\Configuration;

trait FakerTestTrait
{
private static int|null $currentSeed = null;
private static int|null $savedSeed = null;

#[BeforeClass(10)]
public static function __saveAndResetFakerSeed(): void
{
self::$savedSeed = Configuration::fakerSeed();

self::$currentSeed = null;
Configuration::resetFakerSeed();
}

#[AfterClass(-10)] // @phpstan-ignore argument.type (negative priority should be allowed)
public static function __restoreSeed(): void
{
Configuration::resetFakerSeed();
Configuration::fakerSeed(self::$savedSeed);
}
}

0 comments on commit dd8c733

Please sign in to comment.