Haftungsausschluss: Ich bin kein göttliches Wesen. Was ich sage, ist keine absolute Wahrheit. Scheuen Sie sich nicht, auch die Welt in Frage zu stellen, denn es könnte falsch sein, nicht Sie.
Heutzutage ist für niemanden ein Geheimnis, wie wichtig automatisierte Tests für die Aufrechterhaltung der Qualität und Integrität Ihrer Software sind, und normalerweise reden wir viel über Unit-Tests, aber heute konzentrieren wir uns mehr auf Integrationstests in Symfony Framework.
Okay, okay! Wenn Sie keine Geduld haben, den Artikel zu lesen, habe ich im untenstehenden Link ein Testprojekt mit der Umsetzung dieses Artikels.
https://github.com/joubertredrat/symfony-testcontainers
Heute ist das Symfony Framework eines der ausgereiftesten und stabilsten Frameworks im PHP-Universum und verfügt über verschiedene gut implementierte Lösungen, beispielsweise Integrationstests. Persönlich habe ich jedoch immer gedacht, dass es zwar einfach ist, Integrationstests selbst durchzuführen, die Bereitstellung externer Abhängigkeiten für Tests jedoch nicht immer so einfach war, wie zum Beispiel bei Datenbanken.
Selbst bei Lösungen wie Docker war mir immer noch klar, dass es notwendig ist, die externen Abhängigkeiten für die Tests bereitzustellen, aber es gibt eine sehr interessante Lösung, die diesen Schritt viel einfacher machen kann, die Testcontainer.
Testcontainers ist ein Open-Source-Framework, mit dem Sie auf einfache Weise alle externen Abhängigkeiten bereitstellen können, die Sie mithilfe von Docker benötigen, z. B. Datenbanken, Nachrichtenbroker, Cache-Systeme oder überhaupt Abhängigkeiten im Container.
Der große Vorteil von Testcontainern im Vergleich zu Docker Compose oder einer anderen Art der Container-Orchestrierung besteht darin, dass Sie die Bereitstellung von Containern programmieren können und bereits heute Golang, Java, .NET, Node.js, Python, Rust usw. unterstützen andere Sprachen und natürlich auch PHP!
Mein erster Kontakt mit Testcontainers war bei einem Projekt in Golang und mir gefiel die Möglichkeit, einen MongoDB-Container für die Durchführung der Repository-Tests bereitzustellen, so gut. Danach beschloss ich, dasselbe in meinem persönlichen Projekt in PHP mit dem Symfony Framework zu tun.
Einer der größten Vorteile von Symfony ist die Unterstützung für die Durchführung von Tests, die in PHPUnit integriert sind und über einen funktionsfähigen Kernel verfügen, der den für die Tests erforderlichen Bootstrap durchführt.
Obwohl Testcontainers PHP unterstützen, ist ihre Implementierung neu und Sie können sie unter https://github.com/testcontainers/testcontainers-php einsehen.
Unten sehen wir eine Implementierung des MySQL 8.0-Containers, der eine externe Abhängigkeit dieses Projekts darstellt, sowie den Start des Symfony-Kernels, die Erstellung einer Datenbank und eines Schemas.
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 selbst ausführen, wie unten im Beispiel dargestellt.
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); } }
Wenn Sie eine Reihe von Tests ausführen, können Sie feststellen, dass die Tests im Vergleich zu Komponententests von Tests mit lediglich simuliertem Verhalten langsamer ausgeführt werden. Dies ist jedoch normal, da Testcontainers während dieses Vorgangs den Container bereitstellt, den Sie für die Verwendung in Tests definiert haben .
Endlich ist es mit dieser Funktion möglich, verrückte Dinge zu erreichen, wie zum Beispiel eine 100-prozentige Abdeckung. Glauben Sie es nicht? Überzeugen Sie sich selbst unter https://joubertredrat.github.io/symfony-testcontainers.
Das war's, bis zum nächsten Mal!
Das obige ist der detaillierte Inhalt vonIntegrationstests auf Symfony mit Testcontainern. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!