diff --git a/.env b/.env index 03264939b..c6442fbf4 100644 --- a/.env +++ b/.env @@ -11,3 +11,11 @@ USE_DAMA_DOCTRINE_TEST_BUNDLE="0" USE_FOUNDRY_PHPUNIT_EXTENSION="0" USE_PHP_84_LAZY_OBJECTS="0" PHPUNIT_VERSION="12" # allowed values: 9, 10, 11, 12 + +# Only relevant for "reset-database" testsuite +DATABASE_RESET_MODE="schema" # allowed values: schema, migrate + +# Only relevant for "reset-database" testsuite with DATABASE_RESET_MODE="migrate" +MIGRATION_CONFIGURATION_FILES=[] +#MIGRATION_CONFIGURATION_FILES=["tests/Fixture/ResetDatabase/migration-configs/migration-configuration.php"] +#MIGRATION_CONFIGURATION_FILES=["tests/Fixture/ResetDatabase/migration-configs/migration-configuration-transactional.php", "tests/Fixture/ResetDatabase/migration-configs/migration-dummy.php"] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index adc87dca8..d2afd31ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -112,7 +112,7 @@ jobs: shell: bash test-reset-database: - name: Reset DB - D:${{ matrix.database }} ${{ matrix.use-dama == 1 && ' (dama)' || '' }} ${{ matrix.reset-database-mode == 'migrate' && ' (migrate)' || '' }} ${{ contains(matrix.with-migration-configuration-file, 'transactional') && '(configuration file transactional)' || contains(matrix.with-migration-configuration-file, 'configuration') && '(configuration file)' || '' }}${{ matrix.deps == 'lowest' && ' (lowest)' || '' }} + name: Reset DB - D:${{ matrix.database }} ${{ matrix.use-dama == 1 && ' (dama)' || '' }} ${{ matrix.reset-database-mode == 'migrate' && ' (migrate)' || '' }} ${{ contains(matrix.migration-configuration-file, ',') && '(multi configuration files)' || contains(matrix.migration-configuration-file, 'transactional') && '(configuration file transactional)' || contains(matrix.migration-configuration-file, 'configuration') && '(configuration file)' || '' }}${{ matrix.deps == 'lowest' && ' (lowest)' || '' }} runs-on: ubuntu-latest strategy: fail-fast: false @@ -120,19 +120,25 @@ jobs: database: [ mysql, pgsql, sqlite, mysql|mongo ] use-dama: [ 0, 1 ] reset-database-mode: [ schema, migrate ] - migration-configuration-file: ['no'] + migration-configuration-file: ['[]'] deps: [ highest, lowest ] include: - - { database: mongo, migration-configuration-file: 'no', use-dama: 0, reset-database-mode: schema } - - { database: pgsql, migration-configuration-file: 'migration-configuration', use-dama: 0, reset-database-mode: migration } - - { database: pgsql, migration-configuration-file: 'migration-configuration-transactional', use-dama: 0, reset-database-mode: migration } + - { database: mongo, migration-configuration-file: '[]', use-dama: 0, reset-database-mode: schema } + - { database: pgsql, migration-configuration-file: '["tests/Fixture/ResetDatabase/migration-configs/migration-configuration.php"]', use-dama: 0, reset-database-mode: migrate } + - { database: pgsql, migration-configuration-file: '["tests/Fixture/ResetDatabase/migration-configs/migration-configuration-transactional.php"]', use-dama: 0, reset-database-mode: migrate } + - + database: pgsql + use-dama: 0 + reset-database-mode: migrate + migration-configuration-file: '["tests/Fixture/ResetDatabase/migration-configs/migration-configuration-transactional.php", "tests/Fixture/ResetDatabase/migration-configs/migration-dummy.php"]' + deps: highest env: DATABASE_URL: ${{ contains(matrix.database, 'mysql') && 'mysql://root:root@localhost:3306/foundry?serverVersion=5.7.42' || contains(matrix.database, 'pgsql') && 'postgresql://root:root@localhost:5432/foundry?serverVersion=15' || 'sqlite:///%kernel.project_dir%/var/data.db' }} MONGO_URL: ${{ contains(matrix.database, 'mongo') && 'mongodb://127.0.0.1:27017/dbName?compressors=disabled&gssapiServiceName=mongodb' || '' }} USE_DAMA_DOCTRINE_TEST_BUNDLE: ${{ matrix.use-dama == 1 && 1 || 0 }} - DATABASE_RESET_MODE: ${{ matrix.reset-database-mode == 1 && 1 || 0 }} - MIGRATION_CONFIGURATION_FILE: ${{ matrix.migration-configuration-file == 'no' && '' || format('tests/Fixture/MigrationTests/configs/{0}.php', matrix.migration-configuration-file) }} - PHPUNIT_VERSION: 11 + DATABASE_RESET_MODE: ${{ matrix.reset-database-mode }} + MIGRATION_CONFIGURATION_FILES: ${{ matrix.migration-configuration-file }} + PHPUNIT_VERSION: 12 services: postgres: image: ${{ contains(matrix.database, 'pgsql') && 'postgres:15' || '' }} @@ -180,7 +186,7 @@ jobs: # We should be able to run the tests twice in order to check if the second run also starts from a fresh db # some bugs could be detected this way - ./phpunit --testsuite reset-database --bootstrap tests/bootstrap-reset-database.php + DATABASE_GENERATE_MIGRATIONS=0 ./phpunit --testsuite reset-database --bootstrap tests/bootstrap-reset-database.php shell: bash test-no-framework: @@ -293,7 +299,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.2 + php-version: 8.4 coverage: xdebug ini-values: xdebug.mode=coverage diff --git a/README.md b/README.md index e66a91662..3b05ccf3d 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ $ composer update $ ./phpunit # run "migrate" testsuite (with "migrate" reset database strategy) -$ ./phpunit --testsuite reset-database +$ ./phpunit --testsuite reset-database --bootstrap tests/bootstrap-reset-database.php ``` ### Overriding the default configuration @@ -73,7 +73,7 @@ PHPUNIT_VERSION="11" # possible values: 9, 10, 11, 11.4 # test reset database with migrations, # only relevant for "reset-database" testsuite -MIGRATION_CONFIGURATION_FILE="tests/Fixture/MigrationTests/configs/migration-configuration.php" +MIGRATION_CONFIGURATION_FILES="[\"tests/Fixture/ResetDatabase/migration-configs/migration-configuration.php\"]" # run test suite with postgreSQL $ vendor/bin/phpunit diff --git a/composer.json b/composer.json index 51901d40f..86214b5a8 100644 --- a/composer.json +++ b/composer.json @@ -33,6 +33,7 @@ "doctrine/common": "^3.2.2", "doctrine/doctrine-bundle": "^2.10", "doctrine/doctrine-migrations-bundle": "^2.2|^3.0", + "doctrine/migrations": "dev-feat/unfroze-dependencies-after-command as 3.9.5", "doctrine/mongodb-odm": "^2.4", "doctrine/mongodb-odm-bundle": "^4.6|^5.0", "doctrine/orm": "^2.16|^3.0", @@ -64,6 +65,12 @@ "src/symfony_console.php" ] }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/nikophil/migrations" + } + ], "autoload-dev": { "psr-4": { "Zenstruck\\Foundry\\Tests\\": ["tests/"], diff --git a/tests/Fixture/DoctrineCascadeRelationship/DoctrineCascadeRelationshipMetadata.php b/tests/Fixture/DoctrineCascadeRelationship/DoctrineCascadeRelationshipMetadata.php index 7d4240898..7c90c6d10 100644 --- a/tests/Fixture/DoctrineCascadeRelationship/DoctrineCascadeRelationshipMetadata.php +++ b/tests/Fixture/DoctrineCascadeRelationship/DoctrineCascadeRelationshipMetadata.php @@ -56,7 +56,7 @@ public static function allCombinations(array $relationshipFields): iterable if (!\getenv('USE_DAMA_DOCTRINE_TEST_BUNDLE')) { $metadata = self::fromArray($relationshipFields[0]); - yield "{$metadata}\n" => [$metadata]; + yield "{$metadata}" => [$metadata]; return; } diff --git a/tests/Fixture/FoundryTestKernel.php b/tests/Fixture/FoundryTestKernel.php index 2888c691a..6f3dd1a24 100644 --- a/tests/Fixture/FoundryTestKernel.php +++ b/tests/Fixture/FoundryTestKernel.php @@ -60,11 +60,6 @@ public static function hasMongo(): bool return (bool) \getenv('MONGO_URL'); } - public static function usesMigrations(): bool - { - return 'migrate' === \getenv('DATABASE_RESET_MODE'); - } - public static function usesDamaDoctrineTestBundle(): bool { return (bool) \getenv('USE_DAMA_DOCTRINE_TEST_BUNDLE'); diff --git a/tests/Fixture/ResetDatabase/DummyMigration.php b/tests/Fixture/ResetDatabase/DummyMigration.php new file mode 100644 index 000000000..636491759 --- /dev/null +++ b/tests/Fixture/ResetDatabase/DummyMigration.php @@ -0,0 +1,19 @@ +addSql('INSERT INTO address (city) VALUES (\'city\')'); + } +} diff --git a/tests/Fixture/ResetDatabase/ResetDatabaseTestKernel.php b/tests/Fixture/ResetDatabase/ResetDatabaseTestKernel.php index 2cd3d777b..9ebd11b0d 100644 --- a/tests/Fixture/ResetDatabase/ResetDatabaseTestKernel.php +++ b/tests/Fixture/ResetDatabase/ResetDatabaseTestKernel.php @@ -28,7 +28,7 @@ public function registerBundles(): iterable { yield from parent::registerBundles(); - if (FoundryTestKernel::usesMigrations()) { + if (self::usesMigrations()) { yield new DoctrineMigrationsBundle(); } } @@ -38,23 +38,25 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load parent::configureContainer($c, $loader); $c->loadFromExtension('zenstruck_foundry', [ + 'persistence' => ['flush_once' => true], + 'enable_auto_refresh_with_lazy_objects' => self::usePHP84LazyObjects(), 'global_state' => [ GlobalStory::class, GlobalInvokableService::class, ], 'orm' => [ - 'reset' => FoundryTestKernel::usesMigrations() + 'reset' => self::usesMigrations() ? [ 'mode' => ResetDatabaseMode::MIGRATE, 'migrations' => [ - 'configurations' => ($configFile = \getenv('MIGRATION_CONFIGURATION_FILE')) ? [$configFile] : [], + 'configurations' => ($configFile = self::migrationFiles()) ? $configFile : [], ], ] : ['mode' => ResetDatabaseMode::SCHEMA], ], ]); - if (FoundryTestKernel::usesMigrations() && !\getenv('MIGRATION_CONFIGURATION_FILE')) { + if (self::usesMigrations() && self::migrationFiles() === []) { // if no configuration file was given in Foundry's config, let's use the main one as default. $c->loadFromExtension( 'doctrine_migrations', @@ -76,4 +78,34 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load $c->register(MongoResetterDecorator::class)->setAutowired(true)->setAutoconfigured(true); } } + + public static function usesMigrations(): bool + { + return 'migrate' === \getenv('DATABASE_RESET_MODE'); + } + + public static function shouldGenerateMigrations(): bool + { + return '0' !== \getenv('DATABASE_GENERATE_MIGRATIONS'); + } + + /** + * @return list + */ + public static function migrationFiles(): array + { + $files = json_decode(\getenv('MIGRATION_CONFIGURATION_FILES')?: '[]', flags: JSON_THROW_ON_ERROR); + + if (!\is_array($files)) { + throw new \InvalidArgumentException('MIGRATION_CONFIGURATION_FILES must be a JSON array.'); + } + + foreach ($files as $file) { + if (!\file_exists($file)) { + throw new \InvalidArgumentException(\sprintf('Migration configuration file "%s" does not exist.', $file)); + } + } + + return $files; // @phpstan-ignore return.type + } } diff --git a/tests/Fixture/ResetDatabase/migration-configs/migration-configuration-transactional.php b/tests/Fixture/ResetDatabase/migration-configs/migration-configuration-transactional.php index fd4821fc6..09f087e5f 100644 --- a/tests/Fixture/ResetDatabase/migration-configs/migration-configuration-transactional.php +++ b/tests/Fixture/ResetDatabase/migration-configs/migration-configuration-transactional.php @@ -11,7 +11,7 @@ return [ 'migrations_paths' => [ - 'Zenstruck\\Foundry\\Tests\\Fixture\\ResetDatabase\\Migrations' => \dirname(__DIR__, 4).'/var/cache/Migrations', + 'Zenstruck\\Foundry\\Tests\\Fixture\\ResetDatabase\\Migrations' => \dirname(__DIR__, 4).'/var/Migrations', ], 'transactional' => true, ]; diff --git a/tests/Fixture/ResetDatabase/migration-configs/migration-configuration.php b/tests/Fixture/ResetDatabase/migration-configs/migration-configuration.php index c47f48ae0..b897fc47c 100644 --- a/tests/Fixture/ResetDatabase/migration-configs/migration-configuration.php +++ b/tests/Fixture/ResetDatabase/migration-configs/migration-configuration.php @@ -11,7 +11,7 @@ return [ 'migrations_paths' => [ - 'Zenstruck\\Foundry\\Tests\\Fixture\\ResetDatabase\\Migrations' => \dirname(__DIR__, 4).'/var/cache/Migrations', + 'Zenstruck\\Foundry\\Tests\\Fixture\\ResetDatabase\\Migrations' => \dirname(__DIR__, 4).'/var/Migrations', ], 'transactional' => false, ]; diff --git a/tests/Fixture/ResetDatabase/migration-configs/migration-dummy.php b/tests/Fixture/ResetDatabase/migration-configs/migration-dummy.php new file mode 100644 index 000000000..18482046e --- /dev/null +++ b/tests/Fixture/ResetDatabase/migration-configs/migration-dummy.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +return [ + 'migrations_paths' => [ + 'Zenstruck\\Foundry\\Tests\\Fixture\\ResetDatabase' => \dirname(__DIR__), + ], + 'transactional' => false, +]; diff --git a/tests/Integration/ResetDatabase/ResetDatabaseTest.php b/tests/Integration/ResetDatabase/ResetDatabaseTest.php index 0377ef93f..c06fffc76 100644 --- a/tests/Integration/ResetDatabase/ResetDatabaseTest.php +++ b/tests/Integration/ResetDatabase/ResetDatabaseTest.php @@ -26,6 +26,8 @@ use Zenstruck\Foundry\Tests\Fixture\ResetDatabase\MongoResetterDecorator; use Zenstruck\Foundry\Tests\Fixture\ResetDatabase\OrmResetterDecorator; +use Zenstruck\Foundry\Tests\Fixture\ResetDatabase\ResetDatabaseTestKernel; + use function Zenstruck\Foundry\Persistence\persist; use function Zenstruck\Foundry\Persistence\repository; @@ -48,15 +50,7 @@ public function it_generates_valid_schema(): void $output = new BufferedOutput() ); - if (FoundryTestKernel::usesMigrations()) { - // The command actually fails, because of a bug in doctrine ORM 3! - // https://github.com/doctrine/migrations/issues/1406 - self::assertSame(2, $exit, \sprintf('Schema is not valid: %s', $commandOutput = $output->fetch())); - self::assertStringContainsString('1 schema diff(s) detected', $commandOutput); - self::assertStringContainsString('DROP TABLE doctrine_migration_versions', $commandOutput); - } else { - self::assertSame(0, $exit, \sprintf('Schema is not valid: %s', $output->fetch())); - } + self::assertSame(0, $exit, \sprintf('Schema is not valid: %s', $output->fetch())); } /** diff --git a/tests/bootstrap-reset-database.php b/tests/bootstrap-reset-database.php index 3c800926b..745259a3d 100644 --- a/tests/bootstrap-reset-database.php +++ b/tests/bootstrap-reset-database.php @@ -11,7 +11,6 @@ use Symfony\Component\Dotenv\Dotenv; use Symfony\Component\Filesystem\Filesystem; -use Zenstruck\Foundry\Tests\Fixture\FoundryTestKernel; use Zenstruck\Foundry\Tests\Fixture\ResetDatabase\ResetDatabaseTestKernel; use function Zenstruck\Foundry\application; @@ -25,8 +24,9 @@ (new Dotenv())->usePutenv()->loadEnv(__DIR__.'/../.env'); -if (FoundryTestKernel::usesMigrations()) { - $fs->mkdir(__DIR__.'/../var/cache/Migrations'); +if (ResetDatabaseTestKernel::usesMigrations() && ResetDatabaseTestKernel::shouldGenerateMigrations()) { + $fs->remove(__DIR__.'/../var/Migrations'); + $fs->mkdir(__DIR__.'/../var/Migrations'); $kernel = new ResetDatabaseTestKernel('test', true); $kernel->boot(); @@ -36,11 +36,17 @@ runCommand($application, 'doctrine:database:drop --if-exists --force', canFail: true); runCommand($application, 'doctrine:database:create', canFail: true); - $configuration = ''; - if (\getenv('MIGRATION_CONFIGURATION_FILE')) { - $configuration = '--configuration '.\getcwd().'/'.\getenv('MIGRATION_CONFIGURATION_FILE'); + $configurationFiles = ResetDatabaseTestKernel::migrationFiles(); + + if (!$configurationFiles) { + runCommand($application, "doctrine:migrations:diff"); + } else { + foreach ($configurationFiles as $configurationFile) { + $configuration = '--configuration '.\getcwd()."/{$configurationFile}"; + runCommand($application, "doctrine:migrations:diff {$configuration}"); + } } - runCommand($application, "doctrine:migrations:diff {$configuration}"); + runCommand($application, 'doctrine:database:drop --force', canFail: true); $kernel->shutdown();