From 959bb647b982397c7aed7ea7d7cac033d34bd182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Poirier=20Th=C3=A9or=C3=AAt?= Date: Fri, 23 Aug 2024 21:53:45 -0400 Subject: [PATCH] [TesterBundle] PHPUnit DoctrineTransactionExtension base on dama/doctrine-test-bundle --- composer.json | 3 +- composer.lock | 70 +++++++++++++++- config/bundles.php | 1 + .../packages/dama_doctrine_test_bundle.yaml | 5 ++ config/packages/doctrine.yaml | 1 + .../Tests/Transport/DrawTransportTest.php | 2 + .../DoctrineTransactionExtension.php | 80 +++++++++++++++++++ .../DoctrineTransaction/NoTransaction.php | 8 ++ packages/tester-bundle/README.md | 35 ++++++++ phpunit.xml.dist | 1 + symfony.lock | 12 +++ .../Security/TwoFactorAuthorizationTest.php | 33 ++------ .../User/Action/UnlockUserActionTest.php | 2 + 13 files changed, 226 insertions(+), 27 deletions(-) create mode 100644 config/packages/dama_doctrine_test_bundle.yaml create mode 100644 packages/tester-bundle/PHPUnit/Extension/DoctrineTransaction/DoctrineTransactionExtension.php create mode 100644 packages/tester-bundle/PHPUnit/Extension/DoctrineTransaction/NoTransaction.php diff --git a/composer.json b/composer.json index 68a1b140..794385b4 100644 --- a/composer.json +++ b/composer.json @@ -124,7 +124,8 @@ "symfony/twig-bundle": "^6.4.0", "symfony/var-dumper": "^6.4.0", "symfony/var-exporter": "^6.4.0", - "symfony/web-profiler-bundle": "^6.4.0" + "symfony/web-profiler-bundle": "^6.4.0", + "dama/doctrine-test-bundle": "^8.2" }, "replace": { "draw/application": "self.version", diff --git a/composer.lock b/composer.lock index d21c4037..000efd3a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "afa45b5f9c1922d8b63499adcd901de8", + "content-hash": "1c85073d453ff2c2f4ff118ab6f28d1d", "packages": [ { "name": "aws/aws-crt-php", @@ -13075,6 +13075,73 @@ }, "time": "2022-12-20T22:53:13+00:00" }, + { + "name": "dama/doctrine-test-bundle", + "version": "v8.2.0", + "source": { + "type": "git", + "url": "https://github.com/dmaicher/doctrine-test-bundle.git", + "reference": "1f81a280ea63f049d24e9c8ce00e557b18e0ff2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dmaicher/doctrine-test-bundle/zipball/1f81a280ea63f049d24e9c8ce00e557b18e0ff2f", + "reference": "1f81a280ea63f049d24e9c8ce00e557b18e0ff2f", + "shasum": "" + }, + "require": { + "doctrine/dbal": "^3.3 || ^4.0", + "doctrine/doctrine-bundle": "^2.11.0", + "php": "^7.4 || ^8.0", + "psr/cache": "^1.0 || ^2.0 || ^3.0", + "symfony/cache": "^5.4 || ^6.3 || ^7.0", + "symfony/framework-bundle": "^5.4 || ^6.3 || ^7.0" + }, + "require-dev": { + "behat/behat": "^3.0", + "friendsofphp/php-cs-fixer": "^3.27", + "phpstan/phpstan": "^1.2", + "phpunit/phpunit": "^8.0 || ^9.0 || ^10.0 || ^11.0", + "symfony/phpunit-bridge": "^6.3", + "symfony/process": "^5.4 || ^6.3 || ^7.0", + "symfony/yaml": "^5.4 || ^6.3 || ^7.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" + } + }, + "autoload": { + "psr-4": { + "DAMA\\DoctrineTestBundle\\": "src/DAMA/DoctrineTestBundle" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David Maicher", + "email": "mail@dmaicher.de" + } + ], + "description": "Symfony bundle to isolate doctrine database tests and improve test performance", + "keywords": [ + "doctrine", + "isolation", + "performance", + "symfony", + "testing", + "tests" + ], + "support": { + "issues": "https://github.com/dmaicher/doctrine-test-bundle/issues", + "source": "https://github.com/dmaicher/doctrine-test-bundle/tree/v8.2.0" + }, + "time": "2024-05-28T15:41:06+00:00" + }, { "name": "dasprid/enum", "version": "1.0.5", @@ -15420,6 +15487,7 @@ "prefer-lowest": false, "platform": { "ext-ctype": "*", + "ext-dom": "*", "ext-iconv": "*", "ext-json": "*", "ext-mongodb": "*", diff --git a/config/bundles.php b/config/bundles.php index a4b46ba5..fb037109 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -30,4 +30,5 @@ Draw\Bundle\SonataImportBundle\DrawSonataImportBundle::class => ['all' => true], Knp\DoctrineBehaviors\DoctrineBehaviorsBundle::class => ['all' => true], Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], + DAMA\DoctrineTestBundle\DAMADoctrineTestBundle::class => ['test' => true], ]; diff --git a/config/packages/dama_doctrine_test_bundle.yaml b/config/packages/dama_doctrine_test_bundle.yaml new file mode 100644 index 00000000..3482cbae --- /dev/null +++ b/config/packages/dama_doctrine_test_bundle.yaml @@ -0,0 +1,5 @@ +when@test: + dama_doctrine_test: + enable_static_connection: true + enable_static_meta_data_cache: true + enable_static_query_cache: true diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index 95707cef..6f9b7845 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -14,6 +14,7 @@ doctrine: schema_filter: '~^(?!messenger_messages|draw_messenger__message|draw_messenger__message_tag)~' driver: 'pdo_mysql' server_version: '8.0.23' + use_savepoints: true logging: true charset: 'utf8mb4' default_table_options: diff --git a/packages/messenger/Tests/Transport/DrawTransportTest.php b/packages/messenger/Tests/Transport/DrawTransportTest.php index 197045dd..4261d17b 100644 --- a/packages/messenger/Tests/Transport/DrawTransportTest.php +++ b/packages/messenger/Tests/Transport/DrawTransportTest.php @@ -3,6 +3,7 @@ namespace Draw\Component\Messenger\Tests\Transport; use Doctrine\DBAL\Connection; +use Draw\Bundle\TesterBundle\PHPUnit\Extension\DoctrineTransaction\NoTransaction; use Draw\Component\Messenger\Expirable\PurgeableTransportInterface; use Draw\Component\Messenger\Expirable\Stamp\ExpirationStamp; use Draw\Component\Messenger\Searchable\SearchableTransportInterface; @@ -28,6 +29,7 @@ use Symfony\Component\Messenger\Transport\TransportInterface; #[CoversClass(DrawTransport::class)] +#[NoTransaction] class DrawTransportTest extends TestCase { use MockTrait; diff --git a/packages/tester-bundle/PHPUnit/Extension/DoctrineTransaction/DoctrineTransactionExtension.php b/packages/tester-bundle/PHPUnit/Extension/DoctrineTransaction/DoctrineTransactionExtension.php new file mode 100644 index 00000000..da5d47d7 --- /dev/null +++ b/packages/tester-bundle/PHPUnit/Extension/DoctrineTransaction/DoctrineTransactionExtension.php @@ -0,0 +1,80 @@ +registerSubscribers( + new class() implements TestSuiteStartedSubscriber { + public function notify(TestSuiteStarted $event): void + { + $class = $event->testSuite()->name(); + + DoctrineTransactionExtension::startTransactionIfNeeded($class); + } + }, + new class() implements TestSuiteFinishedSubscriber { + public function notify(TestSuiteFinished $event): void + { + DoctrineTransactionExtension::rollBack(); + StaticDriver::setKeepStaticConnections(false); + } + }, + ); + } + + private static function asNoTransaction(string $class): bool + { + if (!class_exists($class)) { + return false; + } + + return (bool) \count((new \ReflectionClass($class))->getAttributes(NoTransaction::class)); + } + + public static function startTransactionIfNeeded(string $class): void + { + if (self::asNoTransaction($class)) { + return; + } + + StaticDriver::setKeepStaticConnections(true); + + static::begin(); + } +} diff --git a/packages/tester-bundle/PHPUnit/Extension/DoctrineTransaction/NoTransaction.php b/packages/tester-bundle/PHPUnit/Extension/DoctrineTransaction/NoTransaction.php new file mode 100644 index 00000000..196c733c --- /dev/null +++ b/packages/tester-bundle/PHPUnit/Extension/DoctrineTransaction/NoTransaction.php @@ -0,0 +1,8 @@ + + + + + +``` + +Also if one of your test should not have transaction you can use the `NoTransaction` attribute on the test class. + +```php + +namespace App\Tests; + +use Draw\Bundle\TesterBundle\PHPUnit\Extension\DoctrineTransaction\NoTransaction; +use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; + +#[NoTransaction] +class MyTest extends KernelTestCase +{ + public function testSomething(): void + { + /*...*/ + } +} +``` \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist index eae99d8e..4d2edb7b 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -39,6 +39,7 @@ + diff --git a/symfony.lock b/symfony.lock index 576a29d2..ad422ef1 100644 --- a/symfony.lock +++ b/symfony.lock @@ -29,6 +29,18 @@ "composer/semver": { "version": "3.2.5" }, + "dama/doctrine-test-bundle": { + "version": "8.2", + "recipe": { + "repo": "github.com/symfony/recipes-contrib", + "branch": "main", + "version": "7.2", + "ref": "896306d79d4ee143af9eadf9b09fd34a8c391b70" + }, + "files": [ + "config/packages/dama_doctrine_test_bundle.yaml" + ] + }, "dasprid/enum": { "version": "1.0.3" }, diff --git a/tests/Controller/Security/TwoFactorAuthorizationTest.php b/tests/Controller/Security/TwoFactorAuthorizationTest.php index e8269bc6..0a94e3c0 100644 --- a/tests/Controller/Security/TwoFactorAuthorizationTest.php +++ b/tests/Controller/Security/TwoFactorAuthorizationTest.php @@ -8,9 +8,8 @@ use Draw\Bundle\TesterBundle\PHPUnit\Extension\SetUpAutowire\AutowireService; use Draw\Bundle\TesterBundle\WebTestCase; use Draw\Component\Tester\PHPUnit\Extension\SetUpAutowire\AutowiredInterface; -use PHPUnit\Framework\Attributes\AfterClass; -use PHPUnit\Framework\Attributes\BeforeClass; use PHPUnit\Framework\Attributes\Depends; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Component\DomCrawler\Crawler; @@ -26,11 +25,9 @@ class TwoFactorAuthorizationTest extends WebTestCase implements AutowiredInterfa private static User $user; - public static function setUpBeforeClass(): void + #[DoesNotPerformAssertions] + public function testCreateUser(): void { - $entityManager = static::getContainer() - ->get(EntityManagerInterface::class); - $user = new User(); $user->setEmail('test-2fa@example.com'); $user->setPlainPassword('test'); @@ -39,28 +36,13 @@ public static function setUpBeforeClass(): void // This role for enabling 2fa as per configuration $user->enableTwoFActorAuthenticationProvider('totp'); - $entityManager->persist($user); - $entityManager->flush(); + $this->entityManager->persist($user); + $this->entityManager->flush(); self::$user = $user; } - #[ - AfterClass, - BeforeClass, - ] - public static function cleanUp(): void - { - static::getContainer() - ->get(EntityManagerInterface::class) - ->createQueryBuilder() - ->delete(User::class, 'user') - ->andWhere('user.email like :email') - ->setParameter('email', 'test-2fa%@example.com') - ->getQuery() - ->execute(); - } - + #[Depends('testCreateUser')] public function testLoginRedirectEnable2fa(): void { static::assertTrue(self::$user->needToEnableTotpAuthenticationEnabled()); @@ -76,6 +58,7 @@ public function testLoginRedirectEnable2fa(): void ); } + #[Depends('testCreateUser')] public function testCancel(): void { $this->client->followRedirects(); @@ -102,7 +85,7 @@ public function testEnable2faInAdminInvalidCode(): void self::$user->setRoles(['ROLE_2FA_ADMIN']); $this->entityManager->flush(); - $crawler = $this->loginToAdmin(); + $this->loginToAdmin(); $crawler = $this->client->submit( $this->client->getCrawler() diff --git a/tests/SonataIntegrationBundle/User/Action/UnlockUserActionTest.php b/tests/SonataIntegrationBundle/User/Action/UnlockUserActionTest.php index cd82efc4..a69904d3 100644 --- a/tests/SonataIntegrationBundle/User/Action/UnlockUserActionTest.php +++ b/tests/SonataIntegrationBundle/User/Action/UnlockUserActionTest.php @@ -5,6 +5,7 @@ use App\Tests\SonataIntegrationBundle\WebTestCaseTrait; use Draw\Bundle\UserBundle\Entity\UserLock; use Draw\Component\Tester\PHPUnit\Extension\SetUpAutowire\AutowiredInterface; +use PHPUnit\Framework\Attributes\Depends; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; class UnlockUserActionTest extends WebTestCase implements AutowiredInterface @@ -46,6 +47,7 @@ public function testUnlock(): void static::assertEqualsWithDelta(new \DateTimeImmutable('+ 24 hours'), $userLock->getUnlockUntil(), 2); } + #[Depends('testUnlock')] public function testNoAccess(): void { $this->login('locked@example.com');