Skip to content

Commit e800c83

Browse files
authored
[feature] add option to use doctrine migrations to reset database (#145)
1 parent 8466067 commit e800c83

File tree

8 files changed

+174
-35
lines changed

8 files changed

+174
-35
lines changed

.github/workflows/ci.yml

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ jobs:
3535
- php: 7.2
3636
stability: '@stable'
3737
versions: lowest
38-
- php: 8.0
39-
stability: '@dev'
40-
versions: highest
38+
# - php: 8.0
39+
# stability: '@dev'
40+
# versions: highest
4141
steps:
4242
- name: Checkout code
4343
uses: actions/checkout@v2.3.3
@@ -84,6 +84,18 @@ jobs:
8484
USE_FOUNDRY_BUNDLE: 1
8585
DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7
8686

87+
- name: 'Test: MySQL, DoctrineMigrationsBundle'
88+
run: vendor/bin/simple-phpunit -v
89+
env:
90+
FOUNDRY_RESET_MODE: migrate
91+
DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7
92+
93+
- name: 'Test: MySQL, DoctrineMigrationsBundle, DAMABundle'
94+
run: vendor/bin/simple-phpunit -v --configuration phpunit-dama-doctrine.xml.dist
95+
env:
96+
FOUNDRY_RESET_MODE: migrate
97+
DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7
98+
8799
- name: 'Test: PostgreSQL'
88100
run: vendor/bin/simple-phpunit -v
89101
env:
@@ -189,6 +201,18 @@ jobs:
189201
USE_FOUNDRY_BUNDLE: 1
190202
DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7
191203

204+
- name: 'Test: MySQL, DoctrineMigrationsBundle'
205+
run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=mysql-migrations.clover
206+
env:
207+
FOUNDRY_RESET_MODE: migrate
208+
DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7
209+
210+
- name: 'Test: MySQL, DoctrineMigrationsBundle, DAMABundle'
211+
run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=mysql-migrations-dama.clover --configuration phpunit-dama-doctrine.xml.dist
212+
env:
213+
FOUNDRY_RESET_MODE: migrate
214+
DATABASE_URL: mysql://root:1234@127.0.0.1:3306/zenstruck_foundry?serverVersion=5.7
215+
192216
- name: 'Coverage: PostgreSQL'
193217
run: vendor/bin/simple-phpunit -v --coverage-text --coverage-clover=postgres.clover
194218
env:

README.md

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,25 @@ Want to watch a screencast 🎥 about it? Check out https://symfonycasts.com/fou
4343
4. [Using with DoctrineFixturesBundle](#using-with-doctrinefixturesbundle)
4444
5. [Using in your Tests](#using-in-your-tests)
4545
1. [Enable Foundry in your TestCase](#enable-foundry-in-your-testcase)
46-
2. [Object Proxy](#object-proxy)
46+
2. [Database Reset](#database-reset)
47+
3. [Object Proxy](#object-proxy)
4748
1. [Force Setting](#force-setting)
4849
2. [Auto-Refresh](#auto-refresh)
49-
3. [Repository Proxy](#repository-proxy)
50-
4. [Assertions](#assertions)
51-
5. [Global State](#global-state)
52-
6. [PHPUnit Data Providers](#phpunit-data-providers)
53-
7. [Performance](#performance)
50+
4. [Repository Proxy](#repository-proxy)
51+
5. [Assertions](#assertions)
52+
6. [Global State](#global-state)
53+
7. [PHPUnit Data Providers](#phpunit-data-providers)
54+
8. [Performance](#performance)
5455
1. [DAMADoctrineTestBundle](#damadoctrinetestbundle)
5556
2. [Miscellaneous](#miscellaneous)
56-
8. [Non-Kernel Test](#non-kernel-tests)
57-
9. [Test-Only Configuration](#test-only-configuration)
58-
10. [Using without the Bundle](#using-without-the-bundle)
59-
7. [Stories](#stories)
57+
9. [Non-Kernel Test](#non-kernel-tests)
58+
10. [Test-Only Configuration](#test-only-configuration)
59+
11. [Using without the Bundle](#using-without-the-bundle)
60+
6. [Stories](#stories)
6061
1. [Stories as Services](#stories-as-services)
6162
2. [Story State](#story-state)
62-
8. [Bundle Configuration](#bundle-configuration)
63-
9. [Credit](#credit)
63+
7. [Bundle Configuration](#bundle-configuration)
64+
8. [Credit](#credit)
6465

6566
## Installation
6667

@@ -1024,8 +1025,10 @@ class MyTest extends WebTestCase
10241025
}
10251026
```
10261027

1027-
This library requires that your database be reset before each test. The packaged `ResetDatabase` trait handles this for
1028-
you. Before the first test, it drops (if exists) and creates the test database. Before each test, it resets the schema.
1028+
### Database Reset
1029+
1030+
This library requires that your database be reset before each test. The packaged `ResetDatabase` trait handles
1031+
this for you.
10291032

10301033
```php
10311034
use Zenstruck\Foundry\Test\Factories;
@@ -1040,6 +1043,15 @@ class MyTest extends WebTestCase
10401043
}
10411044
```
10421045

1046+
Before the first test using the `ResetDatabase` trait, it drops (if exists) and creates the test database.
1047+
Then, by default, before each test, it resets the schema using `doctrine:schema:drop`/`doctrine:schema:create`.
1048+
1049+
Alternatively, you can have it run your migrations instead by setting the env variable `FOUNDRY_RESET_MODE=migrate`
1050+
(in your `.env.test`). When using this *mode*, before each test, the database is dropped/created and your migrations
1051+
run (via `doctrine:migrations:migrate`). This mode can really make your test suite slow (especially if you have a lot
1052+
of migrations). It is highly recommended to use [DamaDoctrineTestBundle](#damadoctrinetestbundle) to improve the
1053+
speed. When this bundle is enabled, the database is dropped/created and migrated only once for the suite.
1054+
10431055
**TIP**: Create a base TestCase for tests using factories to avoid adding the traits to every TestCase.
10441056

10451057
**NOTE**: If your tests [are not persisting](#without-persisting) the objects they create, these test traits are not

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,12 @@
2222
"require-dev": {
2323
"dama/doctrine-test-bundle": "^6.0",
2424
"doctrine/doctrine-bundle": "^2.0",
25+
"doctrine/doctrine-migrations-bundle": "^2.2|^3.0",
2526
"doctrine/orm": "^2.7",
2627
"matthiasnoback/symfony-dependency-injection-test": "^4.1",
2728
"psalm/plugin-symfony": "^1.5|^2.0",
2829
"symfony/framework-bundle": "^4.4|^5.0",
29-
"symfony/maker-bundle": "^1.13",
30+
"symfony/maker-bundle": "^1.30",
3031
"symfony/phpunit-bridge": "^5.2",
3132
"vimeo/psalm": "^3.18|^4.0"
3233
},

run-tests

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,13 @@ echo "Running with FoundryBundle and with DamaDoctrineTestBundle"
2121
echo "=========================================================="
2222
echo ""
2323
USE_FOUNDRY_BUNDLE=1 vendor/bin/simple-phpunit -c phpunit-dama-doctrine.xml
24+
25+
echo "Running with DoctineMigrationsBundle and without DamaDoctrineTestBundle"
26+
echo "======================================================================="
27+
echo ""
28+
USE_FOUNDRY_BUNDLE=0 FOUNDRY_RESET_MODE=migrate vendor/bin/simple-phpunit
29+
30+
echo "Running with DoctineMigrationsBundle and with DamaDoctrineTestBundle"
31+
echo "===================================================================="
32+
echo ""
33+
USE_FOUNDRY_BUNDLE=0 FOUNDRY_RESET_MODE=migrate vendor/bin/simple-phpunit -c phpunit-dama-doctrine.xml

src/Test/DatabaseResetter.php

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,28 @@ public static function resetDatabase(KernelInterface $kernel): void
3939
$application = self::createApplication($kernel);
4040
$registry = $kernel->getContainer()->get('doctrine');
4141

42+
self::dropAndCreateDatabase($application, $registry);
43+
self::createSchema($application, $registry);
44+
45+
self::$hasBeenReset = true;
46+
}
47+
48+
public static function resetSchema(KernelInterface $kernel): void
49+
{
50+
$application = self::createApplication($kernel);
51+
$registry = $kernel->getContainer()->get('doctrine');
52+
53+
self::dropSchema($application, $registry);
54+
self::createSchema($application, $registry);
55+
}
56+
57+
private static function isResetUsingMigrations(): bool
58+
{
59+
return 'migrate' === ($_SERVER['FOUNDRY_RESET_MODE'] ?? 'schema');
60+
}
61+
62+
private static function dropAndCreateDatabase(Application $application, ManagerRegistry $registry): void
63+
{
4264
foreach (self::connectionsToReset($registry) as $connection) {
4365
$dropParams = ['--connection' => $connection, '--force' => true];
4466

@@ -53,27 +75,18 @@ public static function resetDatabase(KernelInterface $kernel): void
5375
'--connection' => $connection,
5476
]);
5577
}
56-
57-
self::createSchema($application, $registry);
58-
59-
self::$hasBeenReset = true;
60-
}
61-
62-
public static function resetSchema(KernelInterface $kernel): void
63-
{
64-
$application = self::createApplication($kernel);
65-
$registry = $kernel->getContainer()->get('doctrine');
66-
67-
self::dropSchema($application, $registry);
68-
self::createSchema($application, $registry);
6978
}
7079

7180
private static function createSchema(Application $application, ManagerRegistry $registry): void
7281
{
73-
foreach (self::objectManagersToReset($registry) as $manager) {
74-
self::runCommand($application, 'doctrine:schema:create', [
75-
'--em' => $manager,
76-
]);
82+
if (self::isResetUsingMigrations()) {
83+
self::runCommand($application, 'doctrine:migrations:migrate', ['-n' => true]);
84+
} else {
85+
foreach (self::objectManagersToReset($registry) as $manager) {
86+
self::runCommand($application, 'doctrine:schema:create', [
87+
'--em' => $manager,
88+
]);
89+
}
7790
}
7891

7992
if (!Factory::isBooted()) {
@@ -85,6 +98,12 @@ private static function createSchema(Application $application, ManagerRegistry $
8598

8699
private static function dropSchema(Application $application, ManagerRegistry $registry): void
87100
{
101+
if (self::isResetUsingMigrations()) {
102+
self::dropAndCreateDatabase($application, $registry);
103+
104+
return;
105+
}
106+
88107
foreach (self::objectManagersToReset($registry) as $manager) {
89108
self::runCommand($application, 'doctrine:schema:drop', [
90109
'--em' => $manager,

tests/Fixtures/Kernel.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use DAMA\DoctrineTestBundle\DAMADoctrineTestBundle;
66
use Doctrine\Bundle\DoctrineBundle\DoctrineBundle;
7+
use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle;
78
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
89
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
910
use Symfony\Bundle\MakerBundle\MakerBundle;
@@ -36,6 +37,10 @@ public function registerBundles(): iterable
3637
if (\getenv('USE_DAMA_DOCTRINE_TEST_BUNDLE')) {
3738
yield new DAMADoctrineTestBundle();
3839
}
40+
41+
if ('migrate' === \getenv('FOUNDRY_RESET_MODE')) {
42+
yield new DoctrineMigrationsBundle();
43+
}
3944
}
4045

4146
protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader): void
@@ -81,6 +86,14 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load
8186
'auto_refresh_proxies' => false,
8287
]);
8388
}
89+
90+
if ('migrate' === \getenv('FOUNDRY_RESET_MODE')) {
91+
$c->loadFromExtension('doctrine_migrations', [
92+
'migrations_paths' => [
93+
'Zenstruck\Foundry\Tests\Fixtures\Migrations' => '%kernel.project_dir%/tests/Fixtures/Migrations',
94+
],
95+
]);
96+
}
8497
}
8598

8699
protected function configureRoutes(RouteCollectionBuilder $routes): void
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Zenstruck\Foundry\Tests\Fixtures\Migrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
final class Version20210218175742 extends AbstractMigration
11+
{
12+
public function getDescription(): string
13+
{
14+
return 'First migration.';
15+
}
16+
17+
public function up(Schema $schema): void
18+
{
19+
$this->addSql('CREATE TABLE categories (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
20+
$this->addSql('CREATE TABLE comments (id INT AUTO_INCREMENT NOT NULL, user_id INT NOT NULL, post_id INT NOT NULL, body LONGTEXT NOT NULL, createdAt DATETIME NOT NULL, approved TINYINT(1) NOT NULL, INDEX IDX_5F9E962AA76ED395 (user_id), INDEX IDX_5F9E962A4B89032C (post_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
21+
$this->addSql('CREATE TABLE contacts (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, address_value VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
22+
$this->addSql('CREATE TABLE posts (id INT AUTO_INCREMENT NOT NULL, category_id INT DEFAULT NULL, title VARCHAR(255) NOT NULL, body LONGTEXT NOT NULL, shortDescription VARCHAR(255) DEFAULT NULL, viewCount INT NOT NULL, createdAt DATETIME NOT NULL, publishedAt DATETIME DEFAULT NULL, INDEX IDX_885DBAFA12469DE2 (category_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
23+
$this->addSql('CREATE TABLE post_tag (post_id INT NOT NULL, tag_id INT NOT NULL, INDEX IDX_5ACE3AF04B89032C (post_id), INDEX IDX_5ACE3AF0BAD26311 (tag_id), PRIMARY KEY(post_id, tag_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
24+
$this->addSql('CREATE TABLE tags (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
25+
$this->addSql('CREATE TABLE users (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
26+
}
27+
28+
public function down(Schema $schema): void
29+
{
30+
}
31+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Zenstruck\Foundry\Tests\Fixtures\Migrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
final class Version20210318175742 extends AbstractMigration
11+
{
12+
public function getDescription(): string
13+
{
14+
return 'Second migration.';
15+
}
16+
17+
public function up(Schema $schema): void
18+
{
19+
$this->addSql('ALTER TABLE comments ADD CONSTRAINT FK_5F9E962AA76ED395 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE');
20+
$this->addSql('ALTER TABLE comments ADD CONSTRAINT FK_5F9E962A4B89032C FOREIGN KEY (post_id) REFERENCES posts (id) ON DELETE CASCADE');
21+
$this->addSql('ALTER TABLE posts ADD CONSTRAINT FK_885DBAFA12469DE2 FOREIGN KEY (category_id) REFERENCES categories (id)');
22+
$this->addSql('ALTER TABLE post_tag ADD CONSTRAINT FK_5ACE3AF04B89032C FOREIGN KEY (post_id) REFERENCES posts (id) ON DELETE CASCADE');
23+
$this->addSql('ALTER TABLE post_tag ADD CONSTRAINT FK_5ACE3AF0BAD26311 FOREIGN KEY (tag_id) REFERENCES tags (id) ON DELETE CASCADE');
24+
}
25+
26+
public function down(Schema $schema): void
27+
{
28+
}
29+
}

0 commit comments

Comments
 (0)