Haftungsausschluss: Ich bin kein göttliches Wesen. Was ich sage, ist keine absolute Wahrheit. Haben Sie keine Angst, selbst die Welt in Frage zu stellen, denn es könnte falsch sein, nicht Sie.
Heutzutage ist es für niemanden ein Geheimnis, wie wichtig automatisierte Tests sind, um die Qualität und Integrität Ihrer Software aufrechtzuerhalten, und wir reden normalerweise viel über Unit-Tests, heute konzentrieren wir uns jedoch mehr auf Integrationstests im Symfony Framework.
Okay, okay! Wenn Sie nicht die Geduld haben, diesen Artikel zu lesen, habe ich unter dem folgenden Link ein Testprojekt zur Umsetzung dieses Artikels.
https://github.com/joubertredrat/symfony-testcontainers
Heute ist das Symfony Framework eines der ausgereiftesten Frameworks im PHP-Universum und verfügt über mehrere gut implementierte Lösungen, beispielsweise für Integrationstests. Persönlich habe ich jedoch immer festgestellt, dass es zwar einfach ist, die Integrationstests selbst durchzuführen, die Bereitstellung externer Abhängigkeiten für die Tests jedoch nicht immer so einfach war, wie zum Beispiel Datenbanken.
Selbst mit dem Aufkommen von Docker wurde mir immer noch klar, dass es notwendig ist, externe Abhängigkeiten auf irgendeine Weise zum Testen bereitzustellen. Es gibt jedoch eine sehr interessante Lösung, die diesen Schritt viel einfacher machen kann: Testcontainer.
Testcontainers ist ein Open-Source-Framework, mit dem Sie mithilfe von Docker einfacher alle externen Abhängigkeiten bereitstellen können, die Sie benötigen, z. B. eine Datenbank, einen Nachrichtenbroker, Caching-Systeme oder praktisch jede Containerabhängigkeit.
Der große Unterschied zwischen Testcontainern in Bezug auf Docker Compose oder jede andere Form der Containerbereitstellung besteht darin, dass Sie die Containerbereitstellung programmieren können und sie bereits heute Unterstützung für Golang, Java, .NET, Node.js, Python, Rust usw. bietet. mehrere andere Sprachen und natürlich PHP!
Mein erster Kontakt mit Testcontainers war bei einem Golang-Projekt und mir gefiel die einfache Bereitstellung eines MongoDB-Containers zum Durchführen meiner Tests in den Repositorys sehr. Danach habe ich beschlossen, dasselbe in einem persönlichen Projekt zu tun, an dem ich beteiligt bin PHP mit dem Symfony Framework.
Einer der großen Vorteile von Symfony ist genau die Unterstützung für Tests in PHPUnit, indem ein voll funktionsfähiger Kernel bereitgestellt wird, um den notwendigen Bootstrap für Tests durchzuführen.
Obwohl Testcontainers PHP unterstützt, ist die Implementierung neuer und Sie können sie unter https://github.com/testcontainers/testcontainers-php nachlesen.
Unten sehen wir eine Implementierung eines MySQL 8.0-Containers, der neben dem Booten des Symfony-Kernels und der Erstellung der Datenbank und des Schemas die externe Abhängigkeit dieses Projekts darstellt.
class IntegrationTestCase extends KernelTestCase { protected static ?MySQLContainer $container = null; public static function setUpBeforeClass(): void { parent::setUpBeforeClass(); if (!static::$container) { static::$container = MySQLContainer::make('8.0', 'password'); static::$container->withPort('19306', '3306'); static::$container->run(); $kernel = self::bootKernel(); $container = $kernel->getContainer(); $application = new Application($kernel); $application->setAutoExit(false); $application->run( new ArrayInput(['command' => 'doctrine:database:create', '--if-not-exists' => true]) ); $entityManager = $container->get('doctrine')->getManager(); $metadata = $entityManager->getMetadataFactory()->getAllMetadata(); $schemaTool = new SchemaTool($entityManager); $schemaTool->dropSchema($metadata); $schemaTool->createSchema($metadata); } } public static function tearDownAfterClass(): void { parent::tearDownAfterClass(); if (static::$container instanceof MySQLContainer) { static::$container->remove(); } }
Damit haben wir die Basisklasse für die Klassen, die die Tests tatsächlich ausführen, wie im Beispiel unten.
class UserRepositoryTest extends IntegrationTestCase { public function testSave(): void { $user = new User(); $user->setName('John Doe'); $user->setEmail('john@doe.local'); $repo = $this->getRepository(); $repo->save($user, true); self::assertNotNull($user->getId()); self::assertIsInt($user->getId()); self::assertTrue($user->getId() > 0); } public function testGetByEmail(): void { $user = new User(); $user->setName('John Doe'); $user->setEmail('john2@doe.local'); $repo = $this->getRepository(); $userNotFound = $repo->getByEmail($user->getEmail()); self::assertNull($userNotFound); $repo->save($user, true); $userFound = $repo->getByEmail($user->getEmail()); self::assertEquals($user->getEmail(), $userFound->getEmail()); } protected function tearDown(): void { parent::tearDown(); $connection = $this ->getContainer() ->get('doctrine') ->getManager() ->getConnection() ; $connection->executeStatement('TRUNCATE TABLE users'); } protected function getRepository(): UserRepository { return $this->getContainer()->get(UserRepository::class); } }
Beim Ausführen der Testsuite werden Sie eine Verzögerung beim Abschluss der Tests bemerken. Dies ist jedoch normal, da Testcontainers während dieses Vorgangs den Container bereitstellt, den Sie für die Verwendung in den Tests definiert haben.
Endlich können Sie mit dieser Leichtigkeit sogar verrückte Dinge ausprobieren, wie zum Beispiel eine 100-prozentige Abdeckung. Glauben Sie es nicht? Sie können es selbst unter https://joubertredrat.github.io/symfony-testcontainers sehen.
Das war's also, bis zum nächsten Mal!
Das obige ist der detaillierte Inhalt vonIntegrationstests in Symfony mit Testcontainern. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!