diff --git a/.env b/.env
new file mode 100644
index 000000000..15f50770b
--- /dev/null
+++ b/.env
@@ -0,0 +1,3 @@
+DATABASE_URL="mysql://root:1234@127.0.0.1:3307/foundry_test?serverVersion=5.7.42"
+MONGO_URL="mongodb://127.0.0.1:27018/dbName?compressors=disabled&gssapiServiceName=mongodb"
+USE_FOUNDRY_BUNDLE=1
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 556d11011..37e207c4d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -8,76 +8,71 @@ on:
 
 jobs:
   tests:
-    name: PHP ${{ matrix.php }}, SF ${{ matrix.symfony }} - ${{ matrix.deps }} ${{ matrix.use-orm == '1' && (matrix.orm-db == 'postgres' && '- ORM (postgres)' || '- ORM (mysql)') || '' }} ${{ matrix.use-odm == '1' && '- ODM' || '' }} ${{ matrix.use-dama == '1' && '- DAMA' || '' }}
+    name: P:${{ matrix.php }}, S:${{ matrix.symfony }}, D:${{ matrix.database }}${{ matrix.deps == 'lowest' && ' (lowest)' || '' }}
     runs-on: ubuntu-latest
     strategy:
-      fail-fast: false
       matrix:
-        php: [8.0, 8.1, 8.2]
-        symfony: [5.4.*, 6.2.*, 6.3.*]
-        deps: [highest]
-        use-orm: [1]
-        use-odm: [1]
-        use-dama: [1]
-        orm-db: [postgres]
-        exclude:
-          - {use-orm: 0, use-odm: 0} # tested directly in a test case
-          - {use-orm: 0, use-dama: 1} # cannot happen
-          # conflicts
-          - {php: 8.0, symfony: 6.2.*}
-          - {php: 8.0, symfony: 6.3.*}
+        php: [ 8.1, 8.2 ]
+        deps: [ highest ]
+        symfony: [ 6.3.*, 6.4.* ]
+        database: [ mysql, mongo ]
+        use-dama: [ 1 ]
         include:
-          - {php: 8.0, symfony: 5.4.*, use-orm: 1, use-odm: 0, use-dama: 0, deps: lowest, orm-db: postgres}
-          - {php: 8.0, symfony: 5.4.*, use-orm: 1, use-odm: 1, use-dama: 0, deps: lowest, orm-db: postgres}
-          - {php: 8.0, symfony: 5.4.*, use-orm: 0, use-odm: 1, use-dama: 0, deps: lowest, orm-db: postgres}
-          - {php: 8.2, symfony: 6.3.*, use-orm: 1, use-odm: 0, use-dama: 0, deps: highest, orm-db: postgres}
-          - {php: 8.2, symfony: 6.3.*, use-orm: 1, use-odm: 1, use-dama: 0, deps: highest, orm-db: postgres}
-          - {php: 8.2, symfony: 6.3.*, use-orm: 1, use-odm: 0, use-dama: 1, deps: highest, orm-db: postgres}
-          - {php: 8.2, symfony: 6.3.*, use-orm: 0, use-odm: 1, use-dama: 0, deps: highest, orm-db: postgres}
-          - {php: 8.2, symfony: 6.3.*, use-orm: 1, use-odm: 0, use-dama: 1, deps: highest, orm-db: mysql}
-          - {php: 8.2, symfony: 6.3.*, use-orm: 1, use-odm: 0, use-dama: 0, deps: highest, orm-db: mysql}
-
+          - php: 8.0
+            deps: lowest
+            symfony: '5.4.*'
+            database: mysql|mongo
+          - php: 8.2
+            deps: highest
+            symfony: '*'
+            database: none
+          - php: 8.2
+            deps: highest
+            symfony: '*'
+            database: mysql|mongo
+          - php: 8.2
+            deps: highest
+            symfony: '*'
+            database: pgsql|mongo
+          - php: 8.2
+            deps: highest
+            symfony: '*'
+            database: mysql
+            use-dama: 0
+          - php: 8.2
+            deps: highest
+            symfony: '*'
+            database: pgsql
+            use-dama: 0
+    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' || '' }}
+      MONGO_URL: ${{ contains(matrix.database, 'mongo') && 'mongodb://127.0.0.1:27017/dbName?compressors=disabled&gssapiServiceName=mongodb' || '' }}
     services:
-      mysql:
-        image: mysql:5.7.42
-        env:
-          MYSQL_ROOT_PASSWORD: 1234
-        ports:
-          - 3306:3306
-        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
-
       postgres:
-        image: postgres:15
+        image: ${{ contains(matrix.database, 'pgsql') && 'postgres:15' || '' }}
         env:
-          POSTGRES_USER: postgres
-          POSTGRES_DB: zenstruck_foundry_${{ matrix.use-dama }}_${{ matrix.orm-db }}
-          POSTGRES_PASSWORD: 1234
-        options: --health-cmd pg_isready --health-interval=10s --health-timeout=5s --health-retries=5
+          POSTGRES_USER: root
+          POSTGRES_PASSWORD: root
+          POSTGRES_DB: foundry
         ports:
           - 5432:5432
-
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
       mongo:
-        image: mongo:4
+        image: ${{ contains(matrix.database, 'mongo') && 'mongo:4' || '' }}
         ports:
           - 27017:27017
-
-    env:
-      MYSQL_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7.42
-      PGSQL_URL: postgresql://postgres:1234@127.0.0.1:5432/zenstruck_foundry_${{ matrix.use-dama }}_${{ matrix.orm-db }}?charset=utf8&serverVersion=15
-      MONGO_URL: mongodb://127.0.0.1:27017/dbName?compressors=disabled&gssapiServiceName=mongodb
-
     steps:
       - name: Checkout code
         uses: actions/checkout@v3
 
-      - name: Verify MySQL version
-        run: mysql --host 127.0.0.1 -uroot -p1234 -e "STATUS"
-
       - name: Setup PHP
         uses: shivammathur/setup-php@v2
         with:
           php-version: ${{ matrix.php }}
-          extensions: pgsql, sqlite, mongodb
           coverage: none
           tools: flex
 
@@ -89,51 +84,48 @@ jobs:
         env:
           SYMFONY_REQUIRE: ${{ matrix.symfony }}
 
-      - name: 'Test'
-        run: |
-          if [ "${{ matrix.use-dama }}" == "1" ]; then
-            CONFIGURATION="--configuration phpunit-dama-doctrine.xml.dist"
-          fi
+      - name: Set up MySQL
+        if: contains(matrix.database, 'mysql')
+        run: sudo /etc/init.d/mysql start
 
-          vendor/bin/simple-phpunit ${CONFIGURATION}
+      - name: Test with "dama"
+        run: TEST_MIGRATIONS=1 vendor/bin/phpunit -c "${PHPUNIT_CONFIG_FILE}"
+        shell: bash
         env:
-          USE_ORM: ${{ matrix.use-orm }}
-          USE_ODM: ${{ matrix.use-odm }}
-          USE_FOUNDRY_BUNDLE: 1
-          DATABASE_URL: ${{ matrix.orm-db == 'postgres' && env.PGSQL_URL || env.MYSQL_URL }}
+          PHPUNIT_CONFIG_FILE: ${{ matrix.use-dama == 1 && contains(matrix.database, 'sql') && 'phpunit.dama.xml.dist' || 'phpunit.xml.dist' }}
 
   code-coverage:
     name: Code Coverage
     runs-on: ubuntu-latest
+    env:
+      DATABASE_URL: postgresql://root:root@localhost:5432/foundry?serverVersion=15
+      MONGO_URL: mongodb://127.0.0.1:27017/dbName?compressors=disabled&gssapiServiceName=mongodb
     services:
-      mysql:
-        image: mysql:5.7
-        env:
-          MYSQL_ROOT_PASSWORD: 1234
-        ports:
-          - 3306:3306
-        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
       mongo:
         image: mongo:4
         ports:
           - 27017:27017
-
-    env:
-      DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7
-      MONGO_URL: mongodb://127.0.0.1:27017/dbName?compressors=disabled&gssapiServiceName=mongodb
-
+      postgres:
+        image: postgres:15
+        env:
+          POSTGRES_USER: root
+          POSTGRES_PASSWORD: root
+          POSTGRES_DB: foundry
+        ports:
+          - 5432:5432
+        options: >-
+          --health-cmd pg_isready
+          --health-interval 10s
+          --health-timeout 5s
+          --health-retries 5
     steps:
       - name: Checkout code
         uses: actions/checkout@v3
 
-      - name: Verify MySQL version
-        run: mysql --host 127.0.0.1 -uroot -p1234 -e "STATUS"
-
       - name: Setup PHP
         uses: shivammathur/setup-php@v2
         with:
-          php-version: 8.0
-          extensions: pgsql, sqlite
+          php-version: 8.2
           coverage: xdebug
           ini-values: xdebug.mode=coverage
 
@@ -141,44 +133,19 @@ jobs:
         uses: ramsey/composer-install@v2
         with:
           composer-options: --prefer-dist
-          dependency-versions: "highest"
 
-      - name: 'Coverage'
-        run: vendor/bin/simple-phpunit -v --configuration phpunit-dama-doctrine.xml.dist --coverage-text --coverage-clover=foundry.clover
-        env:
-          USE_ORM: 1
-          USE_ODM: 1
-          USE_FOUNDRY_BUNDLE: 1
+      - name: Test with coverage
+        run: USE_FOUNDRY_BUNDLE=0 vendor/bin/phpunit --coverage-text --coverage-clover coverage.xml
+        shell: bash
 
       - name: Publish coverage report to Codecov
         uses: codecov/codecov-action@v3
         with:
-          file: ./*.clover
+          file: ./coverage.xml
 
   composer-validate:
     uses: zenstruck/.github/.github/workflows/php-composer-validate.yml@main
 
-  build-docs:
-    name: Build Documentation
-    runs-on: ubuntu-latest
-    steps:
-      - name: Checkout code
-        uses: actions/checkout@v3
-
-      - name: Setup PHP
-        uses: shivammathur/setup-php@v2
-        with:
-          php-version: 8.0
-          coverage: none
-
-      - name: Install dependencies
-        uses: ramsey/composer-install@v2
-        with:
-          composer-options: --prefer-dist
-
-      - name: Build docs
-        run: bin/build-docs
-
   static-analysis:
     name: Static Analysis
     runs-on: ubuntu-latest
@@ -189,7 +156,7 @@ jobs:
       - name: Setup PHP
         uses: shivammathur/setup-php@v2
         with:
-          php-version: 8.0
+          php-version: 8.1
           coverage: none
 
       - name: Install dependencies
@@ -209,47 +176,6 @@ jobs:
       - name: Run Psalm on factories generated with maker
         run: bin/tools/psalm/vendor/vimeo/psalm/psalm
 
-  test-docker-stack:
-    name: CI with docker stack
-    runs-on: ubuntu-latest
-    strategy:
-      fail-fast: false
-      matrix:
-        php: ['8.0', '8.1', '8.2']
-    steps:
-      - name: Checkout code
-        uses: actions/checkout@v3
-
-      - name: Run test suite with docker
-        run: |
-          echo "PHP_VERSION=${{ matrix.php }}" > .env
-          make validate
-
-  push_docker_images:
-    name: Push docker images after CI complete on main branch
-    needs: [tests, composer-validate, build-docs, static-analysis, test-docker-stack]
-    runs-on: ubuntu-latest
-    if: ${{ github.event_name == 'push' && github.event.ref == 'refs/heads/1.x' }}
-    strategy:
-      fail-fast: false
-      matrix:
-        php: ['8.0', '8.1', '8.2']
-    steps:
-      - name: Checkout code
-        uses: actions/checkout@v3
-
-      - name: Login to ghcr.io
-        uses: docker/login-action@v2
-        with:
-          registry: ghcr.io/zenstruck
-          username: token
-          password: ${{ secrets.PACKAGE_PUSH_TOKEN }}
-
-      - name: Build and push images
-        run: ./docker/build.sh push ${{ matrix.php }}
-        env:
-          GITHUB_TOKEN: ${{ secrets.PACKAGE_PUSH_TOKEN }}
-
   fixcs:
     name: Run php-cs-fixer
     needs: sync-with-template
@@ -271,4 +197,3 @@ jobs:
         with:
           key: ${{ secrets.GPG_PRIVATE_KEY }}
           token: ${{ secrets.COMPOSER_TOKEN }}
-          phpcsconfig: false
diff --git a/.gitignore b/.gitignore
index 9060a9233..f73429c20 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,5 +9,7 @@
 /tests/Fixtures/tmp
 /var/
 /docs/output/
-/.env
 /docker/.makefile
+/.env.local
+/docker-compose.override.yaml
+/tests/Fixtures/Migrations/
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 5bad441a5..000000000
--- a/Makefile
+++ /dev/null
@@ -1,176 +0,0 @@
-.DEFAULT_GOAL := help
-
-SHELL=/bin/bash
-
-# DB variables
-PGSQL_URL="postgresql://zenstruck:zenstruck@postgres:5432/zenstruck_foundry?serverVersion=15"
-MONGO_URL="mongodb://mongo:mongo@mongo:27017/mongo?compressors=disabled&gssapiServiceName=mongodb&authSource=mongo"
-
-# Default test context variables
-USE_FOUNDRY_BUNDLE=1
-USE_ORM=1
-USE_ODM=1
-USE_DAMA_DOCTRINE_TEST_BUNDLE=1
-SYMFONY_REQUIRE=5.4.*
-PHP_VERSION=8.0
-PREFER_LOWEST=false
-
-# Override test context variables with `.env` file
-ifneq (,$(wildcard .env))
-	include .env
-	export $(shell sed 's/=.*//' .env)
-endif
-
-ifeq (${PREFER_LOWEST},1)
-	COMPOSER_UPDATE_OPTIONS=--prefer-dist --prefer-lowest
-else
-	COMPOSER_UPDATE_OPTIONS=--prefer-dist
-endif
-
-DOCKER_PHP_CONTAINER_FLAG := docker/.makefile/.docker-containers-${PHP_VERSION}
-PHPSTAN_BIN := bin/tools/phpstan/vendor/phpstan/phpstan/phpstan
-PSALM_BIN := bin/tools/psalm/vendor/vimeo/psalm/psalm
-
-ifeq ($(USE_DAMA_DOCTRINE_TEST_BUNDLE),1)
-	PHPUNIT_CONFIG_FILE='phpunit-dama-doctrine.xml.dist'
-else
-	PHPUNIT_CONFIG_FILE='phpunit.xml.dist'
-endif
-
-# Define docker executable
-ifeq ($(shell docker --help | grep "compose"),)
-	DOCKER_COMPOSE := COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose
-else
-	DOCKER_COMPOSE := COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker compose
-endif
-
-# Create special context for CI
-INTERACTIVE:=$(shell [ -t 0 ] && echo 1)
-ifdef INTERACTIVE
-	DC_EXEC=$(DOCKER_COMPOSE) exec -e USE_FOUNDRY_BUNDLE=${USE_FOUNDRY_BUNDLE} -e DATABASE_URL=${PGSQL_URL} -e MONGO_URL=${MONGO_URL}
-else
-	# CI needs to be ran in no-tty mode
-	DC_EXEC=$(DOCKER_COMPOSE) exec -e USE_FOUNDRY_BUNDLE=${USE_FOUNDRY_BUNDLE} -e DATABASE_URL=${PGSQL_URL} -e MONGO_URL=${MONGO_URL} -T
-endif
-
-PHP=php${PHP_VERSION}
-DOCKER_PHP=${DC_EXEC} ${PHP}
-DOCKER_PHP_WITHOUT_XDEBUG=${DOCKER_PHP} php -d 'xdebug.mode=off'
-
-ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
-$(eval $(RUN_ARGS):;@:)
-
-.PHONY: help
-help:
-	@fgrep -h "###" $(MAKEFILE_LIST) | fgrep -v fgrep | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
-
-.PHONY: validate
-validate: sca psalm test database-validate-mapping ### Run sca, full test suite and validate migrations
-
-.PHONY: test
-test: vendor ### Run PHPUnit tests suite
-	@$(MAKE) --no-print-directory docker-start-if-not-running
-	@${DC_EXEC} -e USE_ORM=${USE_ORM} -e USE_ODM=${USE_ODM} ${PHP} vendor/bin/simple-phpunit --configuration ${PHPUNIT_CONFIG_FILE} $(ARGS)
-
-.PHONY: sca
-sca: phpstan ### Run static analysis
-
-.PHONY: phpstan
-phpstan: $(PHPSTAN_BIN)
-	@$(MAKE) --no-print-directory docker-start-if-not-running
-	@${DOCKER_PHP_WITHOUT_XDEBUG} $(PHPSTAN_BIN) analyse
-
-$(PHPSTAN_BIN): vendor bin/tools/phpstan/composer.json bin/tools/phpstan/composer.lock
-	@$(MAKE) --no-print-directory docker-start-if-not-running
-	@${DOCKER_PHP_WITHOUT_XDEBUG} /usr/bin/composer bin phpstan install
-	@touch -c $@ bin/tools/phpstan/composer.json bin/tools/phpstan/composer.lock
-
-# Psalm is only used to validate factories generated thanks to make:factory command.
-.PHONY: psalm
-psalm: $(PSALM_BIN)
-	@$(MAKE) --no-print-directory docker-start-if-not-running
-	@${DOCKER_PHP_WITHOUT_XDEBUG} $(PSALM_BIN)
-
-$(PSALM_BIN): vendor bin/tools/psalm/composer.json bin/tools/psalm/composer.lock
-	@$(MAKE) --no-print-directory docker-start-if-not-running
-	@${DOCKER_PHP_WITHOUT_XDEBUG} /usr/bin/composer bin psalm install
-	@touch -c $@ bin/tools/psalm/composer.json bin/tools/psalm/composer.lock
-
-.PHONY: docs
-docs: vendor ### Generate documentation to docs/output
-	@$(MAKE) --no-print-directory docker-start-if-not-running
-	@${DOCKER_PHP} ./bin/build-docs
-
-.PHONY: database-generate-migration
-database-generate-migration: database-drop-schema ### Generate new migration based on mapping in Zenstruck\Foundry\Tests\Fixtures\Entity
-	@${DOCKER_PHP} vendor/bin/doctrine-migrations migrations:migrate --no-interaction --allow-no-migration # first, let's load into db existing migrations
-	@${DOCKER_PHP} vendor/bin/doctrine-migrations migrations:diff --no-interaction
-	@${DOCKER_PHP} vendor/bin/doctrine-migrations migrations:migrate --no-interaction # load the new migration
-	@${DOCKER_PHP} bin/doctrine orm:validate-schema
-
-.PHONY: database-validate-mapping
-database-validate-mapping: database-drop-schema ### Validate mapping in Zenstruck\Foundry\Tests\Fixtures\Entity
-	@${DOCKER_PHP} vendor/bin/doctrine-migrations migrations:migrate --no-interaction --allow-no-migration
-	@${DOCKER_PHP} bin/doctrine orm:validate-schema
-
-.PHONY: database-drop-schema
-database-drop-schema: vendor ### Drop database schema
-	@$(MAKE) --no-print-directory docker-start-if-not-running
-	@${DOCKER_PHP} bin/doctrine orm:schema-tool:drop --force
-	@${DOCKER_PHP} vendor/bin/doctrine-migrations migrations:sync-metadata-storage # prevents the next command to fail if migrations table does not exist
-	@${DOCKER_PHP} bin/doctrine dbal:run-sql "TRUNCATE doctrine_migration_versions" --quiet
-
-.PHONY: composer
-composer: ### Run composer command
-	@$(MAKE) --no-print-directory docker-start-if-not-running
-	@${DOCKER_PHP_WITHOUT_XDEBUG} /usr/bin/composer $(ARGS)
-
-vendor: $(DOCKER_PHP_CONTAINER_FLAG) composer.json $(wildcard composer.lock) $(wildcard .env)
-	@$(MAKE) --no-print-directory docker-start-if-not-running
-	@${DC_EXEC} -e SYMFONY_REQUIRE=${SYMFONY_REQUIRE} ${PHP} php -d 'xdebug.mode=off' /usr/bin/composer update ${COMPOSER_UPDATE_OPTIONS}
-	@touch -c $@ composer.json .env composer.lock
-
-.PHONY: docker-start-if-not-running
-docker-start-if-not-running:
-	@if [ -f "$(DOCKER_PHP_CONTAINER_FLAG)" ] ; then \
-		if $(DOCKER_COMPOSE) ps -a | grep "${PHP}" | grep -q -v 'Up '; then \
-		    $(MAKE) --no-print-directory docker-start; \
-		fi; \
-	fi
-
-.PHONY: docker-build
-docker-build: ### Build and start containers
-	@rm -f $(DOCKER_PHP_CONTAINER_FLAG)
-	@$(MAKE) --no-print-directory $(DOCKER_PHP_CONTAINER_FLAG)
-
-.PHONY: docker-start
-docker-start: ### Start containers
-	@echo -e "\nStarting containers. This could take up to one minute.\n"
-	@$(DOCKER_COMPOSE) up --detach --no-build --remove-orphans postgres mongo "${PHP}";
-
-.PHONY: docker-stop
-docker-stop: ### Stop containers
-	@rm $(DOCKER_PHP_CONTAINER_FLAG)
-	@$(DOCKER_COMPOSE) stop
-
-.PHONY: docker-purge
-docker-purge: docker-stop ### Purge containers
-	@$(DOCKER_COMPOSE) down --volumes
-
-$(DOCKER_PHP_CONTAINER_FLAG):
-	@./docker/build.sh load "${PHP_VERSION}"
-	@$(MAKE) --no-print-directory docker-start
-	@echo ""
-	@$(DOCKER_COMPOSE) ps
-	@echo ""
-	@${DOCKER_PHP} php -v
-	@echo ""
-	@mkdir -p docker/.makefile/
-	@touch $@
-
-.PHONY: clear
-clear: ### Start from a fresh install (use it for troubleshooting)
-	rm -rf composer.lock vendor/ bin/tools/*/vendor/ docker/.makefile
-
-%: # black hole to prevent extra args warning
-	@:
diff --git a/README.md b/README.md
index dc1af9c55..97fd06c0c 100644
--- a/README.md
+++ b/README.md
@@ -30,89 +30,89 @@ Want to watch a screencast 🎥 about it? Check out https://symfonycasts.com/fou
 
 ## How to contribute
 
-The test suite of this library needs one or more database, and static analysis needs to be ran on the smaller PHP version
-supported (currently PHP 7.2), then it comes with a full docker stack.
-
-### Install docker
-
-You must [install docker](https://docs.docker.com/engine/install/) and [install docker-compose](https://docs.docker.com/compose/install/)
-at first before running the tests.
-
-### Run tests
-
-The library is shipped with a `Makefile` to run tests.
-Each target will build and start the docker stack and install composer only if needed.
-
-```shell
-$ make help
-validate                       Run sca, full test suite and validate migrations
-test                           Run PHPUnit tests suite
-sca                            Run static analysis
-docs                           Generate documentation to docs/output
-database-generate-migration    Generate new migration based on mapping in Zenstruck\Foundry\Tests\Fixtures\Entity
-database-validate-mapping      Validate mapping in Zenstruck\Foundry\Tests\Fixtures\Entity
-database-drop-schema           Drop database schema
-composer                       Run composer command
-docker-start                   Build and run containers
-docker-stop                    Stop containers
-docker-purge                   Purge containers
-clear                          Start from a fresh install (use it for troubleshooting)
-```
+### Running the Test Suite
 
-Use double-dash to pass any PHPUnit options or arguments with `make`:
-```shell
-$ make test -- --stop-on-failure
-$ make test -- --filter FactoryTest
-# don't use "=" options value. ie: don't do this:
-$ make test -- --filter=FactoryTest
-```
+The test suite of this library needs one or more databases, then it comes with a docker compose configuration.
 
-Same syntax is available for composer:
-```shell
-$ make composer -- info symfony/*
-```
+> [!NOTE]
+> Docker and PHP installed locally (with `pgsql` & `mongodb` extensions) is required.
 
-#### Run tests in different environments
+You can start the containers and run the test suite:
 
-You can create a `.env` file to change the context in which tests will execute:
-```dotenv
-USE_ORM=1
-USE_ODM=1
-USE_DAMA_DOCTRINE_TEST_BUNDLE=1
-SYMFONY_REQUIRE=5.4.* # allowed values: 5.4.* | 6.0.* | 6.1.* | 6.2.*
-PHP_VERSION=8.0 # allowed values: 8.0 | 8.1 | 8.2
-PREFER_LOWEST=1 # force composer to request lowest dependencies
-```
+```bash
+# start the container
+$ docker compose up --detach
 
-### Change docker's ports
+# install dependencies
+$ composer update
 
-You can also add these variables to the `.env` file to change the ports used by docker:
-```dotenv
-PGSQL_PORT=5434
-MONGO_PORT=27018
+# run test suite with all available permutations
+$ composer test
+
+# run only one permutation
+$ vendor/bin/phpunit
+
+# run test suite with dama/doctrine-test-bundle
+$ vendor/bin/phpunit -c phpunit.dama.xml.dist
+
+# run test suite with postgreSQL instead of MySQL
+$ DATABASE_URL="postgresql://zenstruck:zenstruck@127.0.0.1:5433/zenstruck_foundry?serverVersion=15" vendor/bin/phpunit
 ```
 
-### Execute commands in php container
+### Overriding the default configuration
+
+You can override default environment variables by creating a `.env.local` file, to easily enable permutations:
 
-You can execute any command into the php container using docker compose:
-```shell
-$ docker-compose exec php [your commmand] # or "docker compose" depending on your compose version
+```bash
+# .env.local
+DATABASE_URL="postgresql://zenstruck:zenstruck@127.0.0.1:5433/zenstruck_foundry?serverVersion=15"
+
+# run test suite with postgreSQL
+$ vendor/bin/phpunit
 ```
 
-### Using xdebug with PhpStorm
+The `.env.local` file can also be used to override the port of the database containers,
+if it does not meet your local requirements. You'll also need to override docker compose configuration:
 
-The php container is shipped with xdebug activated. You can use step by step debugging session with PhpStorm: you should
-create a server called `FOUNDRY` in your PHP Remote Debug, with the IDE key `xdebug_foundry`
+Here is an example to use MySQL on port `3308`:
 
-![PhpStorm with xdebug](docs/phpstorm-xdebug-config.png)
+```yaml
+# docker-compose.override.yml
+version: '3.9'
 
-### Troubleshooting
+services:
+    mysql:
+        ports:
+            - "3308:3306"
+```
 
-IF any problem occurs with the docker stack or a `make` target, try to run `make clear`.
+```dotenv
+# .env.local
+DATABASE_URL="mysql://root:1234@127.0.0.1:3308/foundry_test?serverVersion=5.7.42"
+```
 
 ## Migrations
 
-Whenever an entity in the fixtures is added or updated a migration must be generated with `make migrations-generate`
+Whenever an entity in the fixtures is added or updated a migration must be generated.
+You can use the following code:
+
+> [!WARNING]
+> Migrations in Foundry's test suite are made for PostgreSQL.
+> So you need to enable PostgreSQL instead of MySQL to use them.
+
+```bash
+# Apply already existing migrations
+$ vendor/bin/doctrine-migrations migrations:migrate --no-interaction --allow-no-migration
+
+# Create a new migration file in /tests/Fixtures/Migrations
+$ vendor/bin/doctrine-migrations migrations:diff --no-interaction
+
+# Load the new migration
+$ vendor/bin/doctrine-migrations migrations:migrate --no-interaction
+
+# Validates the schema
+$ bin/doctrine orm:validate-schema
+```
 
 ## Credit
 
diff --git a/bin/console b/bin/console
new file mode 100755
index 000000000..5944a814f
--- /dev/null
+++ b/bin/console
@@ -0,0 +1,10 @@
+#!/usr/bin/env php
+<?php
+
+use Symfony\Bundle\FrameworkBundle\Console\Application;
+use Zenstruck\Foundry\Tests\Fixtures\Kernel;
+
+require_once __DIR__ . '/../tests/bootstrap.php';
+
+$application = new Application(new Kernel('test', true));
+$application->run();
diff --git a/composer.json b/composer.json
index d3604ff56..17e00032e 100644
--- a/composer.json
+++ b/composer.json
@@ -26,10 +26,12 @@
         "dama/doctrine-test-bundle": "^7.0",
         "doctrine/doctrine-bundle": "^2.5",
         "doctrine/doctrine-migrations-bundle": "^2.2|^3.0",
-        "doctrine/mongodb-odm": "^2.0",
+        "doctrine/mongodb-odm": "^2.4",
         "doctrine/mongodb-odm-bundle": "^4.4.0",
-        "doctrine/orm": "^2.9",
+        "doctrine/orm": "^2.11",
         "matthiasnoback/symfony-dependency-injection-test": "^4.1",
+        "phpunit/phpunit": "^9.5.0",
+        "symfony/dotenv": "^5.4|^6.0|^7.0",
         "symfony/framework-bundle": "^5.4|^6.0|^7.0",
         "symfony/maker-bundle": "^1.49",
         "symfony/phpunit-bridge": "^5.4|^6.0|^7.0",
@@ -65,6 +67,22 @@
             "forward-command": false
         }
     },
+    "scripts": {
+        "test": [
+            "@test-no-dama",
+            "@test-dama",
+            "@test-no-foundry-bundle"
+        ],
+        "test-no-dama": "vendor/bin/phpunit",
+        "test-dama": "vendor/bin/phpunit -c phpunit.dama.xml.dist",
+        "test-no-foundry-bundle": "USE_FOUNDRY_BUNDLE=0 vendor/bin/phpunit -c phpunit.dama.xml.dist"
+    },
+    "scripts-descriptions": {
+        "test": "Run all test permutations",
+        "test-no-dama": "Test without dama/doctrine-test-bundle",
+        "test-dama": "Test with dama/doctrine-test-bundle",
+        "test-no-foundry-bundle": "Test without foundry bundle"
+    },
     "minimum-stability": "dev",
     "prefer-stable": true
 }
diff --git a/config/cli-config.php b/config/cli-config.php
index 1b2b22f83..32cf5a5a4 100644
--- a/config/cli-config.php
+++ b/config/cli-config.php
@@ -6,13 +6,17 @@
 use Doctrine\Migrations\Configuration\Migration\ConfigurationArray;
 use Doctrine\Migrations\DependencyFactory;
 use Doctrine\ORM\EntityManager;
-use Doctrine\ORM\ORMSetup;
+use Doctrine\ORM\Tools\Setup;
+use Symfony\Component\Dotenv\Dotenv;
+
+(new Dotenv())->usePutenv()->loadEnv(__DIR__.'/../.env');
 
 $entities = ['/app/tests/Fixtures/Entity'];
 if (PHP_VERSION_ID >= 80100) {
     $entities[] = '/app/tests/Fixtures/PHP81';
 }
-$ORMconfig = ORMSetup::createAttributeMetadataConfiguration($entities, true);
+$ORMconfig = Setup::createAttributeMetadataConfiguration($entities, true);
+
 $entityManager = EntityManager::create(['memory' => true, 'url' => getenv('DATABASE_URL')], $ORMconfig);
 
 return DependencyFactory::fromEntityManager(
diff --git a/docker-compose.yaml b/docker-compose.yaml
index e2d2b1f73..618efea2a 100644
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -1,41 +1,21 @@
 version: '3.9'
 
 services:
-    php8.0: &php
-        container_name: foundry_php8.0
-        image: ghcr.io/zenstruck/foundry/php:8.0
-        depends_on:
-            postgres:
-                condition: service_healthy
-            mongo:
-                condition: service_healthy
-        volumes:
-            - .:/app
-        working_dir: /app
+    mysql:
+        image: mysql:5.7
+        ports:
+            - "3307:3306"
         environment:
-            PHP_IDE_CONFIG: "serverName=FOUNDRY"
-
-    php8.1:
-        <<: *php
-        container_name: foundry_php8.1
-        image: ghcr.io/zenstruck/foundry/php:8.1
-
-    php8.2:
-        <<: *php
-        container_name: foundry_php8.2
-        image: ghcr.io/zenstruck/foundry/php:8.2
+            MYSQL_ROOT_PASSWORD: 1234
 
     postgres:
-        container_name: foundry_postgres
         image: postgres:15
         environment:
             POSTGRES_DB: zenstruck_foundry
             POSTGRES_PASSWORD: zenstruck
             POSTGRES_USER: zenstruck
-        volumes:
-            - db-data:/var/lib/postgresql/data:rw
         ports:
-            - ${PGSQL_PORT:-5432}:5432
+            - "5433:5432"
         healthcheck:
             test: 'pg_isready -d zenstruck_foundry'
             timeout: 120s
@@ -43,24 +23,10 @@ services:
             interval: 2s
 
     mongo:
-        container_name: foundry_mongo
-        image: mongo:4.4
-        tmpfs:
-            - /data
-        environment:
-            - MONGO_INITDB_ROOT_USERNAME=admin
-            - MONGO_INITDB_ROOT_PASSWORD=admin
-            - MONGO_INITDB_DATABASE=mongo
-            - MONGO_NON_ROOT_USERNAME=mongo
-            - MONGO_NON_ROOT_PASSWORD=mongo
+        image: mongo:4
         ports:
-            - ${MONGO_PORT:-27017}:27017
-        volumes:
-            - ./docker/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
+            - "27018:27017"
         healthcheck:
             test: echo 'db.runCommand("ping").ok' | mongo mongo:27017/test --quiet
             timeout: 10s
             retries: 10
-
-volumes:
-    db-data:
diff --git a/docker/Dockerfile b/docker/Dockerfile
deleted file mode 100644
index 173844861..000000000
--- a/docker/Dockerfile
+++ /dev/null
@@ -1,62 +0,0 @@
-ARG PHP_VERSION
-
-FROM php:${PHP_VERSION}-cli-bullseye
-
-COPY --from=composer:2.4 /usr/bin/composer /usr/bin/composer
-
-RUN set -eux ; \
-    apt-get update ; \
-    apt-get install --no-install-recommends -y \
-        $PHPIZE_DEPS \
-        git \
-        curl \
-        zip \
-        unzip \
-        libicu-dev \
-        git \
-        curl \
-        unzip \
-        procps \
-        dialog \
-        apt-utils \
-        libpq-dev \
-        libcurl4-openssl-dev \
-        pkg-config \
-        libssl-dev \
-    ; \
-    docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql; \
-    docker-php-ext-install pdo pdo_mysql pdo_pgsql pgsql; \
-    pecl install -f mongodb-1.15; \
-    pecl install xdebug ; \
-    docker-php-ext-enable mongodb xdebug ; \
-    pecl clear-cache ; \
-    apt-get remove -y $PHPIZE_DEPS zlib1g-dev libcurl4-openssl-dev pkg-config libssl-dev ; \
-    rm -rf /var/lib/apt/lists/* ; \
-    apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
-
-LABEL org.opencontainers.image.source="https://github.com/zenstruck/foundry"
-
-# We want these last commands to be at the bottom of the file because they depend on the host
-# And we want to benefit of the cache layering as much as possible
-
-COPY docker/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini
-
-# Set user rights
-ARG USER=docker
-
-# this may be overridden to match host's machine user
-ARG UID=1001
-ARG XDEBUG_HOST="172.17.0.1"
-
-RUN addgroup --system --gid ${UID} ${USER} ; \
-    adduser --system --home /home/${USER} --disabled-password --uid ${UID} --ingroup ${USER} ${USER} ; \
-    mkdir -p /app/var ; \
-    chown -R ${USER}:${USER} /app ; \
-    sed -i "s/%xdebug_host%/${XDEBUG_HOST}/g" /usr/local/etc/php/conf.d/xdebug.ini
-
-USER ${USER}
-
-RUN composer global require --no-progress --no-scripts --no-plugins symfony/flex ; \
-    composer global config --no-plugins allow-plugins.symfony/flex true
-
-CMD tail -f /dev/null
diff --git a/docker/build.sh b/docker/build.sh
deleted file mode 100755
index ef1ff7d65..000000000
--- a/docker/build.sh
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/bin/sh
-
-# Build PHP image with buildx
-# usage: ./docker/build.sh [load|push] [8.0|8.1|8.2]
-
-set -e
-
-build() {
-    ACTION=${1}
-    PHP_VERSION=${2}
-
-    DOCKER_IMAGE_TAG="ghcr.io/zenstruck/foundry/php:${PHP_VERSION}"
-
-    # From inside the containers, docker host ip is different in linux and macos
-    UNAME=$(uname -s)
-    if [ "${UNAME}" = "Linux" ]; then
-        XDEBUG_HOST="172.17.0.1"
-    elif [ "${UNAME}" = "Darwin" ]; then
-        XDEBUG_HOST="host.docker.internal"
-    fi
-
-    docker pull ${DOCKER_IMAGE_TAG} || true
-
-    DOCKER_BUILDKIT=1 docker buildx build \
-        --tag "${DOCKER_IMAGE_TAG}" \
-        --cache-from "${DOCKER_IMAGE_TAG}" \
-        --build-arg BUILDKIT_INLINE_CACHE=1 \
-        --build-arg UID="$(id -u)" \
-        --build-arg PHP_VERSION="${PHP_VERSION}" \
-        --build-arg XDEBUG_HOST="${XDEBUG_HOST}" \
-        --file docker/Dockerfile \
-        "--${ACTION}" \
-        .
-}
-
-main() {
-    ACTION="${1:-load}"
-    PHP_VERSION="${2:-8.0}"
-
-    if [ "${ACTION}" != 'push' ] && [ "${ACTION}" != 'load' ]; then
-        echo "Error: action \"${1}\" invalid. Allowed actions are push|load"
-        exit 1;
-    fi
-
-    if [ "${PHP_VERSION}" != '8.0' ] && [ "${PHP_VERSION}" != '8.1' ] && [ "${PHP_VERSION}" != '8.2' ]; then
-        echo "Error: given php version \"${2}\" invalid. Only 8.0, 8.1 and 8.2 are accepted."
-        exit 1;
-    fi
-
-    # ensure default builder is used, it is needed to benefit from cache layering
-    docker buildx use default
-
-    build "${ACTION}" "${PHP_VERSION}"
-}
-
-main "$@"
diff --git a/docker/mongo-init.js b/docker/mongo-init.js
deleted file mode 100644
index d2c2ecbe0..000000000
--- a/docker/mongo-init.js
+++ /dev/null
@@ -1,13 +0,0 @@
-db.createUser(
-    {
-        user: "mongo",
-        pwd: "mongo",
-        roles: [
-            {
-                role: "readWrite",
-                db: "mongo"
-            }
-        ]
-    }
-);
-
diff --git a/docker/xdebug.ini b/docker/xdebug.ini
deleted file mode 100644
index d969fde6c..000000000
--- a/docker/xdebug.ini
+++ /dev/null
@@ -1,12 +0,0 @@
-memory_limit=1024M
-
-[xdebug]
-xdebug.mode=debug
-xdebug.start_with_request=yes
-xdebug.client_host=%xdebug_host%
-xdebug.client_port=9003
-xdebug.idekey=xdebug_foundry
-
-# prevents a warning to be displayed in CLI
-# when phpstorm does not listen incoming connexions
-xdebug.log_level=0
diff --git a/docs/phpstorm-xdebug-config.png b/docs/phpstorm-xdebug-config.png
deleted file mode 100644
index d28c1f434..000000000
Binary files a/docs/phpstorm-xdebug-config.png and /dev/null differ
diff --git a/phpunit-dama-doctrine.xml.dist b/phpunit.dama.xml.dist
similarity index 100%
rename from phpunit-dama-doctrine.xml.dist
rename to phpunit.dama.xml.dist
diff --git a/tests/Fixtures/Kernel.php b/tests/Fixtures/Kernel.php
index d1652f899..6ce61d6b8 100644
--- a/tests/Fixtures/Kernel.php
+++ b/tests/Fixtures/Kernel.php
@@ -54,7 +54,7 @@ public function registerBundles(): iterable
     {
         yield new FrameworkBundle();
 
-        if ($this->enableDoctrine && \getenv('USE_ORM')) {
+        if ($this->enableDoctrine && \getenv('DATABASE_URL')) {
             yield new DoctrineBundle();
         }
 
@@ -68,11 +68,11 @@ public function registerBundles(): iterable
             yield new DAMADoctrineTestBundle();
         }
 
-        if (ORMDatabaseResetter::RESET_MODE_MIGRATE === $this->ormResetMode && $this->enableDoctrine && \getenv('USE_ORM')) {
+        if ($this->withMigrations()) {
             yield new DoctrineMigrationsBundle();
         }
 
-        if ($this->enableDoctrine && \getenv('USE_ODM')) {
+        if ($this->enableDoctrine && \getenv('MONGO_URL')) {
             yield new DoctrineMongoDBBundle();
         }
     }
@@ -81,7 +81,18 @@ public function getCacheDir(): string
     {
         return \sprintf(
             "{$this->getProjectDir()}/var/cache/test/%s",
-            \md5(\json_encode([$this->enableDoctrine, $this->ormResetMode, $this->factoriesRegistered, $this->defaultMakeFactoryNamespace], \JSON_THROW_ON_ERROR))
+            \md5(
+                \json_encode(
+                    [
+                        $this->enableDoctrine,
+                        $this->ormResetMode,
+                        $this->factoriesRegistered,
+                        $this->defaultMakeFactoryNamespace,
+                        $this->withMigrations(),
+                    ],
+                    \JSON_THROW_ON_ERROR
+                )
+            )
         );
     }
 
@@ -107,7 +118,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load
             'test' => true,
         ]);
 
-        if ($this->enableDoctrine && \getenv('USE_ORM')) {
+        if ($this->enableDoctrine && \getenv('DATABASE_URL')) {
             $mappings = [
                 'Test' => [
                     'is_bundle' => false,
@@ -148,14 +159,14 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load
             }
             $globalState = [];
 
-            if ($this->enableDoctrine && \getenv('USE_ORM')) {
+            if ($this->enableDoctrine && \getenv('DATABASE_URL')) {
                 $globalState[] = TagStory::class;
                 $globalState[] = TagStoryAsInvokableService::class;
 
                 $foundryConfig['database_resetter'] = ['orm' => ['reset_mode' => $this->ormResetMode]];
             }
 
-            if ($this->enableDoctrine && \getenv('USE_ODM') && !\getenv('USE_DAMA_DOCTRINE_TEST_BUNDLE')) {
+            if ($this->enableDoctrine && \getenv('MONGO_URL') && !\getenv('USE_DAMA_DOCTRINE_TEST_BUNDLE')) {
                 $globalState[] = ODMTagStory::class;
                 $globalState[] = ODMTagStoryAsAService::class;
                 $c->register(ODMTagStoryAsAService::class)->addTag('foundry.story');
@@ -166,7 +177,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load
             $c->loadFromExtension('zenstruck_foundry', $foundryConfig);
         }
 
-        if (ORMDatabaseResetter::RESET_MODE_MIGRATE === $this->ormResetMode) {
+        if ($this->withMigrations()) {
             $c->loadFromExtension('doctrine_migrations', [
                 'migrations_paths' => [
                     'Zenstruck\Foundry\Tests\Fixtures\Migrations' => '%kernel.project_dir%/tests/Fixtures/Migrations',
@@ -174,7 +185,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load
             ]);
         }
 
-        if ($this->enableDoctrine && \getenv('USE_ODM')) {
+        if ($this->enableDoctrine && \getenv('MONGO_URL')) {
             $mappings = [
                 'Test' => [
                     'is_bundle' => false,
@@ -209,4 +220,9 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load
             ]);
         }
     }
+
+    private function withMigrations(): bool
+    {
+        return $this->enableDoctrine && \getenv('DATABASE_URL') && \getenv('TEST_MIGRATIONS');
+    }
 }
diff --git a/tests/Fixtures/Migrations/Version20230513160345.php b/tests/Fixtures/Migrations/Version20230513160345.php
deleted file mode 100644
index c821d4245..000000000
--- a/tests/Fixtures/Migrations/Version20230513160345.php
+++ /dev/null
@@ -1,91 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Zenstruck\Foundry\Tests\Fixtures\Migrations;
-
-use Doctrine\DBAL\Schema\Schema;
-use Doctrine\Migrations\AbstractMigration;
-
-final class Version20230513160345 extends AbstractMigration
-{
-    public function getDescription(): string
-    {
-        return 'first migration';
-    }
-
-    public function up(Schema $schema): void
-    {
-        $this->addSql('CREATE SEQUENCE categories_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE SEQUENCE comments_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE SEQUENCE contacts_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE SEQUENCE entity_for_relations_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE SEQUENCE entity_with_relations_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE SEQUENCE posts_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE SEQUENCE tags_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE SEQUENCE users_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE TABLE categories (id INT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE TABLE productcategory_product (productcategory_id INT NOT NULL, product_id INT NOT NULL, PRIMARY KEY(productcategory_id, product_id))');
-        $this->addSql('CREATE INDEX IDX_5BC2A6A2E26A32B1 ON productcategory_product (productcategory_id)');
-        $this->addSql('CREATE INDEX IDX_5BC2A6A24584665A ON productcategory_product (product_id)');
-        $this->addSql('CREATE TABLE comments (id INT NOT NULL, user_id INT NOT NULL, post_id INT NOT NULL, body TEXT NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, approved BOOLEAN NOT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE INDEX IDX_5F9E962AA76ED395 ON comments (user_id)');
-        $this->addSql('CREATE INDEX IDX_5F9E962A4B89032C ON comments (post_id)');
-        $this->addSql('CREATE TABLE contacts (id INT NOT NULL, name VARCHAR(255) NOT NULL, address_value VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE TABLE entity_for_relations (id INT NOT NULL, manyToOne_id INT DEFAULT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE INDEX IDX_C63B81552E3A088A ON entity_for_relations (manyToOne_id)');
-        $this->addSql('CREATE TABLE entity_with_relations (id INT NOT NULL, oneToOne_id INT NOT NULL, oneToOneNullable_id INT DEFAULT NULL, manyToOne_id INT NOT NULL, manyToOneNullable_id INT DEFAULT NULL, manyToOneNullableDefault_id INT DEFAULT NULL, manyToOneWithNotExistingFactory_id INT NOT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE UNIQUE INDEX UNIQ_A9C9EC969017888C ON entity_with_relations (oneToOne_id)');
-        $this->addSql('CREATE UNIQUE INDEX UNIQ_A9C9EC96DA2BFB84 ON entity_with_relations (oneToOneNullable_id)');
-        $this->addSql('CREATE INDEX IDX_A9C9EC962E3A088A ON entity_with_relations (manyToOne_id)');
-        $this->addSql('CREATE INDEX IDX_A9C9EC968097B86C ON entity_with_relations (manyToOneNullable_id)');
-        $this->addSql('CREATE INDEX IDX_A9C9EC968572C13C ON entity_with_relations (manyToOneNullableDefault_id)');
-        $this->addSql('CREATE INDEX IDX_A9C9EC96FF92FDCA ON entity_with_relations (manyToOneWithNotExistingFactory_id)');
-        $this->addSql('CREATE TABLE entitywithrelations_category (entitywithrelations_id INT NOT NULL, category_id INT NOT NULL, PRIMARY KEY(entitywithrelations_id, category_id))');
-        $this->addSql('CREATE INDEX IDX_CD6EBFAB337AA4F7 ON entitywithrelations_category (entitywithrelations_id)');
-        $this->addSql('CREATE INDEX IDX_CD6EBFAB12469DE2 ON entitywithrelations_category (category_id)');
-        $this->addSql('CREATE TABLE posts (id INT NOT NULL, category_id INT DEFAULT NULL, secondary_category_id INT DEFAULT NULL, title VARCHAR(255) NOT NULL, body TEXT NOT NULL, shortDescription VARCHAR(255) DEFAULT NULL, viewCount INT NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, publishedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, mostRelevantRelatedPost_id INT DEFAULT NULL, lessRelevantRelatedPost_id INT DEFAULT NULL, type VARCHAR(255) NOT NULL, specificProperty VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE INDEX IDX_885DBAFA12469DE2 ON posts (category_id)');
-        $this->addSql('CREATE INDEX IDX_885DBAFAEA0D7566 ON posts (secondary_category_id)');
-        $this->addSql('CREATE INDEX IDX_885DBAFAD126F51 ON posts (mostRelevantRelatedPost_id)');
-        $this->addSql('CREATE INDEX IDX_885DBAFA20DBE482 ON posts (lessRelevantRelatedPost_id)');
-        $this->addSql('CREATE TABLE post_tag (post_id INT NOT NULL, tag_id INT NOT NULL, PRIMARY KEY(post_id, tag_id))');
-        $this->addSql('CREATE INDEX IDX_5ACE3AF04B89032C ON post_tag (post_id)');
-        $this->addSql('CREATE INDEX IDX_5ACE3AF0BAD26311 ON post_tag (tag_id)');
-        $this->addSql('CREATE TABLE post_tag_secondary (post_id INT NOT NULL, tag_id INT NOT NULL, PRIMARY KEY(post_id, tag_id))');
-        $this->addSql('CREATE INDEX IDX_1515F0214B89032C ON post_tag_secondary (post_id)');
-        $this->addSql('CREATE INDEX IDX_1515F021BAD26311 ON post_tag_secondary (tag_id)');
-        $this->addSql('CREATE TABLE post_post (post_source INT NOT NULL, post_target INT NOT NULL, PRIMARY KEY(post_source, post_target))');
-        $this->addSql('CREATE INDEX IDX_93DF0B866FA89B16 ON post_post (post_source)');
-        $this->addSql('CREATE INDEX IDX_93DF0B86764DCB99 ON post_post (post_target)');
-        $this->addSql('CREATE TABLE product_tag (product_id INT NOT NULL, tag_id INT NOT NULL, PRIMARY KEY(product_id, tag_id))');
-        $this->addSql('CREATE INDEX IDX_E3A6E39C4584665A ON product_tag (product_id)');
-        $this->addSql('CREATE INDEX IDX_E3A6E39CBAD26311 ON product_tag (tag_id)');
-        $this->addSql('CREATE TABLE tags (id INT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE TABLE users (id INT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
-        $this->addSql('ALTER TABLE comments ADD CONSTRAINT FK_5F9E962AA76ED395 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE comments ADD CONSTRAINT FK_5F9E962A4B89032C FOREIGN KEY (post_id) REFERENCES posts (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE entity_for_relations ADD CONSTRAINT FK_C63B81552E3A088A FOREIGN KEY (manyToOne_id) REFERENCES entity_with_relations (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE entity_with_relations ADD CONSTRAINT FK_A9C9EC969017888C FOREIGN KEY (oneToOne_id) REFERENCES categories (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE entity_with_relations ADD CONSTRAINT FK_A9C9EC96DA2BFB84 FOREIGN KEY (oneToOneNullable_id) REFERENCES categories (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE entity_with_relations ADD CONSTRAINT FK_A9C9EC962E3A088A FOREIGN KEY (manyToOne_id) REFERENCES categories (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE entity_with_relations ADD CONSTRAINT FK_A9C9EC968097B86C FOREIGN KEY (manyToOneNullable_id) REFERENCES categories (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE entity_with_relations ADD CONSTRAINT FK_A9C9EC968572C13C FOREIGN KEY (manyToOneNullableDefault_id) REFERENCES categories (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE entitywithrelations_category ADD CONSTRAINT FK_CD6EBFAB337AA4F7 FOREIGN KEY (entitywithrelations_id) REFERENCES entity_with_relations (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE entitywithrelations_category ADD CONSTRAINT FK_CD6EBFAB12469DE2 FOREIGN KEY (category_id) REFERENCES categories (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE posts ADD CONSTRAINT FK_885DBAFA12469DE2 FOREIGN KEY (category_id) REFERENCES categories (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE posts ADD CONSTRAINT FK_885DBAFAEA0D7566 FOREIGN KEY (secondary_category_id) REFERENCES categories (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE posts ADD CONSTRAINT FK_885DBAFAD126F51 FOREIGN KEY (mostRelevantRelatedPost_id) REFERENCES posts (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE posts ADD CONSTRAINT FK_885DBAFA20DBE482 FOREIGN KEY (lessRelevantRelatedPost_id) REFERENCES posts (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE post_tag ADD CONSTRAINT FK_5ACE3AF04B89032C FOREIGN KEY (post_id) REFERENCES posts (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE post_tag ADD CONSTRAINT FK_5ACE3AF0BAD26311 FOREIGN KEY (tag_id) REFERENCES tags (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE post_tag_secondary ADD CONSTRAINT FK_1515F0214B89032C FOREIGN KEY (post_id) REFERENCES posts (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE post_tag_secondary ADD CONSTRAINT FK_1515F021BAD26311 FOREIGN KEY (tag_id) REFERENCES tags (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE post_post ADD CONSTRAINT FK_93DF0B866FA89B16 FOREIGN KEY (post_source) REFERENCES posts (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE post_post ADD CONSTRAINT FK_93DF0B86764DCB99 FOREIGN KEY (post_target) REFERENCES posts (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-    }
-
-    public function down(Schema $schema): void
-    {
-    }
-}
diff --git a/tests/Fixtures/Migrations/Version20230513160346.php b/tests/Fixtures/Migrations/Version20230513160346.php
deleted file mode 100644
index 5aca419cd..000000000
--- a/tests/Fixtures/Migrations/Version20230513160346.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Zenstruck\Foundry\Tests\Fixtures\Migrations;
-
-use Doctrine\DBAL\Schema\Schema;
-use Doctrine\Migrations\AbstractMigration;
-
-final class Version20230513160346 extends AbstractMigration
-{
-    public function getDescription(): string
-    {
-        return 'second migration';
-    }
-
-    public function up(Schema $schema): void
-    {
-        $this->addSql('CREATE SEQUENCE brand_cascade_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE SEQUENCE category_cascade_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE SEQUENCE image_cascade_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE SEQUENCE product_cascade_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE SEQUENCE review_cascade_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE SEQUENCE tag_cascade_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE SEQUENCE variant_cascade_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE TABLE brand_cascade (id INT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE TABLE category_cascade (id INT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE TABLE image_cascade (id INT NOT NULL, path VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE TABLE product_cascade (id INT NOT NULL, brand_id INT DEFAULT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE INDEX IDX_D7FE16D844F5D008 ON product_cascade (brand_id)');
-        $this->addSql('CREATE TABLE review_cascade (id INT NOT NULL, product_id INT DEFAULT NULL, ranking INT NOT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE UNIQUE INDEX UNIQ_9DC9B99F4584665A ON review_cascade (product_id)');
-        $this->addSql('CREATE TABLE tag_cascade (id INT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE TABLE variant_cascade (id INT NOT NULL, product_id INT DEFAULT NULL, image_id INT DEFAULT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE INDEX IDX_6982202E4584665A ON variant_cascade (product_id)');
-        $this->addSql('CREATE UNIQUE INDEX UNIQ_6982202E3DA5256D ON variant_cascade (image_id)');
-        $this->addSql('ALTER TABLE product_cascade ADD CONSTRAINT FK_D7FE16D844F5D008 FOREIGN KEY (brand_id) REFERENCES brand_cascade (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE review_cascade ADD CONSTRAINT FK_9DC9B99F4584665A FOREIGN KEY (product_id) REFERENCES product_cascade (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE variant_cascade ADD CONSTRAINT FK_6982202E4584665A FOREIGN KEY (product_id) REFERENCES product_cascade (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE variant_cascade ADD CONSTRAINT FK_6982202E3DA5256D FOREIGN KEY (image_id) REFERENCES image_cascade (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE productcategory_product ADD CONSTRAINT FK_5BC2A6A2E26A32B1 FOREIGN KEY (productcategory_id) REFERENCES category_cascade (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE productcategory_product ADD CONSTRAINT FK_5BC2A6A24584665A FOREIGN KEY (product_id) REFERENCES product_cascade (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE entity_with_relations ADD CONSTRAINT FK_A9C9EC96FF92FDCA FOREIGN KEY (manyToOneWithNotExistingFactory_id) REFERENCES brand_cascade (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE product_tag ADD CONSTRAINT FK_E3A6E39C4584665A FOREIGN KEY (product_id) REFERENCES product_cascade (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-        $this->addSql('ALTER TABLE product_tag ADD CONSTRAINT FK_E3A6E39CBAD26311 FOREIGN KEY (tag_id) REFERENCES tag_cascade (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
-
-        $this->addSql('CREATE SEQUENCE entity_with_property_name_different_from_construct_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE TABLE entity_with_property_name_different_from_construct (id INT NOT NULL, entity_id INT DEFAULT NULL, someField VARCHAR(255) NOT NULL, address_value VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))');
-        $this->addSql('CREATE INDEX IDX_AA016C6381257D5D ON entity_with_property_name_different_from_construct (entity_id)');
-        $this->addSql('ALTER TABLE entity_with_property_name_different_from_construct ADD CONSTRAINT FK_AA016C6381257D5D FOREIGN KEY (entity_id) REFERENCES entity_for_relations (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
-
-        if (PHP_VERSION_ID < 80100) {
-            return;
-        }
-
-        $this->addSql('CREATE SEQUENCE entity_with_enum_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
-        $this->addSql('CREATE TABLE entity_with_enum (id INT NOT NULL, enum VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
-    }
-
-    public function down(Schema $schema): void
-    {
-    }
-}
diff --git a/tests/Functional/Bundle/Maker/MakeFactoryTest.php b/tests/Functional/Bundle/Maker/MakeFactoryTest.php
index eac8febd4..c50a2d423 100644
--- a/tests/Functional/Bundle/Maker/MakeFactoryTest.php
+++ b/tests/Functional/Bundle/Maker/MakeFactoryTest.php
@@ -73,7 +73,7 @@ protected function tearDown(): void
      */
     public function can_create_factory(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
@@ -94,7 +94,7 @@ public function can_create_factory(): void
      */
     public function can_create_factory_interactively(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
@@ -123,7 +123,7 @@ public function can_create_factory_interactively(): void
      */
     public function can_create_factory_in_test_dir(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
@@ -139,7 +139,7 @@ public function can_create_factory_in_test_dir(): void
      */
     public function can_create_factory_in_a_sub_directory(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
@@ -157,7 +157,7 @@ public function can_create_factory_in_a_sub_directory(): void
      */
     public function can_create_factory_in_test_dir_interactively(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
@@ -175,7 +175,7 @@ public function can_create_factory_in_test_dir_interactively(): void
      */
     public function can_create_factory_with_static_analysis_annotations(string $scaTool): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
@@ -194,7 +194,7 @@ public function can_create_factory_with_static_analysis_annotations(string $scaT
      */
     public function can_create_factory_for_entity_with_repository(string $scaTool): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
@@ -267,7 +267,7 @@ public function can_create_factory_for_not_persisted_class_interactively(): void
      */
     public function can_customize_namespace(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
@@ -286,7 +286,7 @@ public function can_customize_namespace(): void
      */
     public function can_customize_namespace_with_test_flag(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
@@ -305,7 +305,7 @@ public function can_customize_namespace_with_test_flag(): void
      */
     public function can_customize_namespace_with_root_namespace_prefix(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
@@ -324,7 +324,7 @@ public function can_customize_namespace_with_root_namespace_prefix(): void
      */
     public function can_customize_namespace_with_test_flag_with_root_namespace_prefix(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
@@ -346,7 +346,7 @@ public function can_create_all_factories_for_doctrine_objects(): void
         $tester = $this->makeFactoryCommandTester();
 
         $inputs = ['All']; // which factory to generate?
-        if (\getenv('USE_ORM')) {
+        if (\getenv('DATABASE_URL')) {
             $inputs[] = 'OtherTagFactory'; // name collision handling (only for ORM, the collision is caused my an ORM class
         }
 
@@ -355,13 +355,13 @@ public function can_create_all_factories_for_doctrine_objects(): void
 
         $expectedFactories = [];
 
-        if (\getenv('USE_ORM')) {
+        if (\getenv('DATABASE_URL')) {
             $expectedFactories = ['Cascade/BrandFactory', 'CategoryFactory', 'CommentFactory', 'ContactFactory', 'EntityForRelationsFactory', 'UserFactory', 'TagFactory', 'Cascade/TagFactory'];
         }
 
-        if (\getenv('USE_ODM')) {
+        if (\getenv('MONGO_URL')) {
             $expectedFactories = [...$expectedFactories, 'ODMCategoryFactory', 'ODMCommentFactory', 'ODMPostFactory', 'ODMUserFactory'];
-            $expectedFactories[] = \getenv('USE_ORM') ? 'OtherTagFactory' : 'TagFactory';
+            $expectedFactories[] = \getenv('DATABASE_URL') ? 'OtherTagFactory' : 'TagFactory';
         }
 
         self::assertGreaterThan(0, \count($expectedFactories));
@@ -376,7 +376,7 @@ public function can_create_all_factories_for_doctrine_objects(): void
      */
     public function can_create_factory_for_odm(string $class, string $file): void
     {
-        if (!\getenv('USE_ODM')) {
+        if (!\getenv('MONGO_URL')) {
             self::markTestSkipped('doctrine/odm not enabled.');
         }
 
@@ -418,7 +418,7 @@ public function can_create_factory_with_auto_activated_not_persisted_option(): v
      */
     public function can_create_factory_with_relation_defaults(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
@@ -434,7 +434,7 @@ public function can_create_factory_with_relation_defaults(): void
      */
     public function can_create_factory_with_relation_for_all_fields(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
@@ -461,11 +461,11 @@ public function can_create_factory_with_embeddable(string $objectClass, string $
 
     public function objectsWithEmbeddableProvider(): iterable
     {
-        if (\getenv('USE_ORM')) {
+        if (\getenv('DATABASE_URL')) {
             yield 'orm' => [Contact::class, 'ContactFactory', 'AddressFactory'];
         }
 
-        if (\getenv('USE_ODM')) {
+        if (\getenv('MONGO_URL')) {
             yield 'odm' => [ODMPost::class, 'ODMPostFactory', 'ODMUserFactory', [CommentFactory::class]];
         }
     }
@@ -487,11 +487,11 @@ public function can_create_factory_with_default_enum(string $class, bool $noPers
 
     public function canCreateFactoryWithDefaultEnumProvider(): iterable
     {
-        if (\getenv('USE_ORM')) {
+        if (\getenv('DATABASE_URL')) {
             yield 'orm' => [EntityWithEnum::class];
         }
 
-        if (\getenv('USE_ODM')) {
+        if (\getenv('MONGO_URL')) {
             yield 'odm' => [DocumentWithEnum::class];
         }
 
@@ -503,7 +503,7 @@ public function canCreateFactoryWithDefaultEnumProvider(): iterable
      */
     public function can_create_factory_for_orm_embedded_class(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/odm not enabled.');
         }
 
@@ -520,7 +520,7 @@ public function can_create_factory_for_orm_embedded_class(): void
      */
     public function it_handles_name_collision(): void
     {
-        if (!\getenv('USE_ORM') || !\getenv('USE_ODM')) {
+        if (!\getenv('DATABASE_URL') || !\getenv('MONGO_URL')) {
             self::markTestSkipped('doctrine/odm and doctrine/orm should be enabled enabled.');
         }
 
@@ -548,7 +548,7 @@ public function it_handles_name_collision(): void
      */
     public function it_uses_default_namespace_from_configuration(string $defaultNamespace): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
diff --git a/tests/Functional/Bundle/Maker/MakerTestCase.php b/tests/Functional/Bundle/Maker/MakerTestCase.php
index 280d3fc30..15cf0a68e 100644
--- a/tests/Functional/Bundle/Maker/MakerTestCase.php
+++ b/tests/Functional/Bundle/Maker/MakerTestCase.php
@@ -29,7 +29,7 @@ public function skipIfNotUsingFoundryBundle(): void
             $this->markTestSkipped('ZenstruckFoundryBundle not enabled.');
         }
 
-        if (!\getenv('USE_ORM') && !\getenv('USE_ODM')) {
+        if (!\getenv('DATABASE_URL') && !\getenv('MONGO_URL')) {
             $this->markTestSkipped('Generating factories for classes not managed by doctrine is not supported.');
         }
     }
diff --git a/tests/Functional/FactoryDoctrineCascadeTest.php b/tests/Functional/FactoryDoctrineCascadeTest.php
index fe6a1e7d9..39f0d01af 100644
--- a/tests/Functional/FactoryDoctrineCascadeTest.php
+++ b/tests/Functional/FactoryDoctrineCascadeTest.php
@@ -34,7 +34,7 @@ final class FactoryDoctrineCascadeTest extends KernelTestCase
 
     protected function setUp(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
     }
diff --git a/tests/Functional/FactoryTest.php b/tests/Functional/FactoryTest.php
index 33c4f760e..da374eee4 100644
--- a/tests/Functional/FactoryTest.php
+++ b/tests/Functional/FactoryTest.php
@@ -37,7 +37,7 @@ final class FactoryTest extends KernelTestCase
 
     protected function setUp(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
     }
diff --git a/tests/Functional/ModelFactoryServiceTest.php b/tests/Functional/ModelFactoryServiceTest.php
index 703ad574a..06f2e178e 100644
--- a/tests/Functional/ModelFactoryServiceTest.php
+++ b/tests/Functional/ModelFactoryServiceTest.php
@@ -28,7 +28,7 @@ final class ModelFactoryServiceTest extends KernelTestCase
 
     protected function setUp(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
     }
diff --git a/tests/Functional/ODMAnonymousFactoryTest.php b/tests/Functional/ODMAnonymousFactoryTest.php
index c7d92c8f2..edab87590 100644
--- a/tests/Functional/ODMAnonymousFactoryTest.php
+++ b/tests/Functional/ODMAnonymousFactoryTest.php
@@ -23,7 +23,7 @@ final class ODMAnonymousFactoryTest extends AnonymousFactoryTest
 {
     protected function setUp(): void
     {
-        if (!\getenv('USE_ODM')) {
+        if (!\getenv('MONGO_URL')) {
             self::markTestSkipped('doctrine/odm not enabled.');
         }
     }
diff --git a/tests/Functional/ODMGlobalStateTest.php b/tests/Functional/ODMGlobalStateTest.php
index 43bb8a499..c858c97a8 100644
--- a/tests/Functional/ODMGlobalStateTest.php
+++ b/tests/Functional/ODMGlobalStateTest.php
@@ -19,7 +19,7 @@ final class ODMGlobalStateTest extends GlobalStateTest
 {
     protected function setUp(): void
     {
-        if (!\getenv('USE_ODM')) {
+        if (!\getenv('MONGO_URL')) {
             self::markTestSkipped('doctrine/odm not enabled.');
         }
 
diff --git a/tests/Functional/ODMModelFactoryTest.php b/tests/Functional/ODMModelFactoryTest.php
index f7f29dc2f..0cd877732 100644
--- a/tests/Functional/ODMModelFactoryTest.php
+++ b/tests/Functional/ODMModelFactoryTest.php
@@ -28,7 +28,7 @@ final class ODMModelFactoryTest extends ModelFactoryTest
 {
     protected function setUp(): void
     {
-        if (!\getenv('USE_ODM')) {
+        if (!\getenv('MONGO_URL')) {
             self::markTestSkipped('doctrine/odm not enabled.');
         }
     }
diff --git a/tests/Functional/ODMProxyTest.php b/tests/Functional/ODMProxyTest.php
index 19e5e1861..643fa122b 100644
--- a/tests/Functional/ODMProxyTest.php
+++ b/tests/Functional/ODMProxyTest.php
@@ -21,7 +21,7 @@ final class ODMProxyTest extends ProxyTest
 {
     protected function setUp(): void
     {
-        if (!\getenv('USE_ODM')) {
+        if (!\getenv('MONGO_URL')) {
             self::markTestSkipped('doctrine/odm not enabled.');
         }
     }
diff --git a/tests/Functional/ODMRepositoryProxyTest.php b/tests/Functional/ODMRepositoryProxyTest.php
index 1f0a00ced..e84ac223a 100644
--- a/tests/Functional/ODMRepositoryProxyTest.php
+++ b/tests/Functional/ODMRepositoryProxyTest.php
@@ -21,7 +21,7 @@ final class ODMRepositoryProxyTest extends RepositoryProxyTest
 {
     protected function setUp(): void
     {
-        if (!\getenv('USE_ODM')) {
+        if (!\getenv('MONGO_URL')) {
             self::markTestSkipped('doctrine/odm not enabled.');
         }
     }
diff --git a/tests/Functional/ORMAnonymousFactoryTest.php b/tests/Functional/ORMAnonymousFactoryTest.php
index 7cd1ddea5..5a93193a5 100644
--- a/tests/Functional/ORMAnonymousFactoryTest.php
+++ b/tests/Functional/ORMAnonymousFactoryTest.php
@@ -23,7 +23,7 @@ final class ORMAnonymousFactoryTest extends AnonymousFactoryTest
 {
     protected function setUp(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
     }
diff --git a/tests/Functional/ORMDatabaseResetterTest.php b/tests/Functional/ORMDatabaseResetterTest.php
index 59453d726..e1b190051 100644
--- a/tests/Functional/ORMDatabaseResetterTest.php
+++ b/tests/Functional/ORMDatabaseResetterTest.php
@@ -28,13 +28,9 @@ public static function setUpBeforeClass(): void
             self::markTestSkipped('The database should not be reset if dama/doctrine-test-bundle is enabled.');
         }
 
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm is not enabled.');
         }
-
-        if (!\str_starts_with(\getenv('DATABASE_URL'), 'postgres')) {
-            self::markTestSkipped('Can only test migrations with postgresql.');
-        }
     }
 
     /**
@@ -60,7 +56,10 @@ public function it_resets_database_correctly(string $resetMode): void
     public function databaseResetterProvider(): iterable
     {
         yield [ORMDatabaseResetter::RESET_MODE_SCHEMA];
-        yield [ORMDatabaseResetter::RESET_MODE_MIGRATE];
+
+        if (getenv('TEST_MIGRATIONS')) {
+            yield [ORMDatabaseResetter::RESET_MODE_MIGRATE];
+        }
     }
 
     protected static function createKernel(array $options = []): KernelInterface
diff --git a/tests/Functional/ORMGlobalStateTest.php b/tests/Functional/ORMGlobalStateTest.php
index a7429c615..a2d4d8bb5 100644
--- a/tests/Functional/ORMGlobalStateTest.php
+++ b/tests/Functional/ORMGlobalStateTest.php
@@ -18,7 +18,7 @@ final class ORMGlobalStateTest extends GlobalStateTest
 {
     protected function setUp(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
diff --git a/tests/Functional/ORMModelFactoryTest.php b/tests/Functional/ORMModelFactoryTest.php
index ef345a8c2..84a7328a8 100644
--- a/tests/Functional/ORMModelFactoryTest.php
+++ b/tests/Functional/ORMModelFactoryTest.php
@@ -37,7 +37,7 @@ final class ORMModelFactoryTest extends ModelFactoryTest
 {
     protected function setUp(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
     }
diff --git a/tests/Functional/ORMProxyTest.php b/tests/Functional/ORMProxyTest.php
index 251295c30..1436ec990 100644
--- a/tests/Functional/ORMProxyTest.php
+++ b/tests/Functional/ORMProxyTest.php
@@ -26,7 +26,7 @@ final class ORMProxyTest extends ProxyTest
 {
     protected function setUp(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
     }
diff --git a/tests/Functional/ORMRepositoryProxyTest.php b/tests/Functional/ORMRepositoryProxyTest.php
index f3cc23ff0..2a6339fd0 100644
--- a/tests/Functional/ORMRepositoryProxyTest.php
+++ b/tests/Functional/ORMRepositoryProxyTest.php
@@ -26,7 +26,7 @@ final class ORMRepositoryProxyTest extends RepositoryProxyTest
 {
     protected function setUp(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
     }
diff --git a/tests/Functional/StoryTest.php b/tests/Functional/StoryTest.php
index 652e1aa87..99f1f51ca 100644
--- a/tests/Functional/StoryTest.php
+++ b/tests/Functional/StoryTest.php
@@ -34,7 +34,7 @@ final class StoryTest extends KernelTestCase
 
     protected function setUp(): void
     {
-        if (!\getenv('USE_ORM')) {
+        if (!\getenv('DATABASE_URL')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
     }
diff --git a/tests/Functional/WithMigrationTest.php b/tests/Functional/WithMigrationTest.php
index 8f23b3e1e..2c11dccf7 100644
--- a/tests/Functional/WithMigrationTest.php
+++ b/tests/Functional/WithMigrationTest.php
@@ -14,7 +14,11 @@
 namespace Zenstruck\Foundry\Tests\Functional;
 
 use Doctrine\ORM\Tools\SchemaValidator;
+use Symfony\Bundle\FrameworkBundle\Console\Application;
 use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
+use Symfony\Component\Console\Input\StringInput;
+use Symfony\Component\Console\Output\NullOutput;
+use Symfony\Component\Filesystem\Filesystem;
 use Symfony\Component\HttpKernel\KernelInterface;
 use Zenstruck\Foundry\Test\ORMDatabaseResetter;
 use Zenstruck\Foundry\Test\ResetDatabase;
@@ -48,15 +52,11 @@ public function it_can_use_schema_reset_with_migration(): void
     protected static function createKernel(array $options = []): KernelInterface
     {
         // ResetDatabase trait uses @beforeClass annotation which would always be called before setUpBeforeClass()
-        // but it also calls "static::createKernel()" which we can use to skip test if USE_ORM is false.
-        if (!\getenv('USE_ORM')) {
+        // but it also calls "static::createKernel()" which we can use to skip test if DATABASE_URL is false.
+        if (!\getenv('DATABASE_URL') || !\getenv('TEST_MIGRATIONS')) {
             self::markTestSkipped('doctrine/orm not enabled.');
         }
 
-        if (!\str_starts_with(\getenv('DATABASE_URL'), 'postgres')) {
-            self::markTestSkipped('Can only test migrations with postgresql.');
-        }
-
         return Kernel::create(true, ORMDatabaseResetter::RESET_MODE_MIGRATE);
     }
 }
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index aac0fe406..5ef599e38 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -9,8 +9,34 @@
  * file that was distributed with this source code.
  */
 
+use Symfony\Bundle\FrameworkBundle\Console\Application;
+use Symfony\Component\Console\Input\StringInput;
+use Symfony\Component\Console\Output\NullOutput;
+use Symfony\Component\Dotenv\Dotenv;
 use Symfony\Component\Filesystem\Filesystem;
+use Zenstruck\Foundry\Tests\Fixtures\Kernel;
 
 require \dirname(__DIR__).'/vendor/autoload.php';
 
-(new Filesystem())->remove(__DIR__.'/../var');
+(new Dotenv())->usePutenv()->loadEnv(__DIR__.'/../.env');
+
+$fs = new Filesystem();
+
+$fs->remove(__DIR__.'/../var');
+
+if (\getenv('DATABASE_URL') && \getenv('TEST_MIGRATIONS')) {
+    $fs->remove(__DIR__.'/Fixtures/Migrations');
+    $fs->mkdir(__DIR__.'/Fixtures/Migrations');
+
+    $kernel = new Kernel('test', true);
+    $kernel->boot();
+
+    $application = new Application($kernel);
+    $application->setAutoExit(false);
+
+    $application->run(new StringInput('doctrine:database:create --if-not-exists --no-interaction'), new NullOutput());
+    $application->run(new StringInput('doctrine:schema:drop --force --no-interaction'), new NullOutput());
+    $application->run(new StringInput('doctrine:migrations:diff --no-interaction'), new NullOutput());
+
+    $kernel->shutdown();
+}