ホームページ  >  記事  >  バックエンド開発  >  Testcontainers を使用した Symfony の統合テスト

Testcontainers を使用した Symfony の統合テスト

王林
王林オリジナル
2024-08-30 06:35:32697ブラウズ

免責事項: 私は神聖な存在ではありません。私の言うことは絶対的な真実ではありません。あなたではなく世界が間違っている可能性があるので、世界に対してさえ疑問を抱くことを恐れないでください。

現在、ソフトウェアの品質と整合性を維持するための自動テストの重要性は誰にとっても秘密ではありません。通常、単体テストについてよく話しますが、今日は Symfony フレームワークの統合テストに重点を置きます。

我慢できなくなったのでコードを見せてください。

わかったわかった!この記事を読む忍耐力がない場合は、以下のリンクにこの記事を実装するテスト プロジェクトがあります。

https://github.com/joubertredrat/symfony-testcontainers

Symfony フレームワークと統合テスト

現在、Symfony フレームワークは PHP の世界で最も成熟したフレームワークの 1 つであり、統合テストなどの適切に実装されたソリューションがいくつかあります。ただし、個人的には、統合テスト自体を実行するのは簡単でも、テストに外部依存関係を提供することは、たとえばデータベースのように必ずしも簡単ではないことに常に気づきました。

Docker が登場しても、テストのために外部の依存関係を何らかの方法でプロビジョニングする必要があることは依然として認識していましたが、このステップをはるかに簡単にする非常に興味深いソリューション、Testcontainers があります。

テストコンテナ

Testcontainers は、Docker を使用して必要な外部依存関係 (データベース、メッセージ ブローカー、キャッシュ システム、または実質的にあらゆるコンテナ依存関係など) をより簡単にプロビジョニングできるオープン ソース フレームワークです。

Docker compose や他の形式のコンテナ プロビジョニングに関する Testcontainers の大きな違いは、コンテナ プロビジョニングをプログラムできることです。現在では、すでに Golang、Java、.NET、Node.js、Python、Rust、他のいくつかの言語、そしてもちろん PHP!

Testcontainers との最初の接触は Golang プロジェクトでした。リポジトリでテストを実行するための MongoDB コンテナのプロビジョニングの容易さがとても気に入りました。その後、私が持っている個人プロジェクトでも同じことを行うことにしました。 Symfony フレームワークを使用した PHP。

Symfony + テストコンテナ = ❤️

Symfony の大きな利点の 1 つは、まさに、テストに必要なブートストラップを実行するための完全に機能するカーネルを提供することによる、PHPUnit でのテストのサポートです。

Testcontainers は PHP をサポートしていますが、実装は新しいものであり、https://github.com/testcontainers/testcontainers-php で確認できます。

以下には、Symfony カーネルの起動、データベースとスキーマの作成に加えて、このプロジェクトの外部依存関係である MySQL 8.0 コンテナの実装があります。

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();
        }
    }

これにより、以下の例にあるように、実際にテストを実行するクラスの基本クラスが完成しました。

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);
    }
}

テスト スイートを実行すると、テストの終了に遅れが生じることがありますが、このプロセス中に Testcontainers がテストで使用するために定義したコンテナをプロビジョニングしているため、これは正常です。

Testes de Integração no Symfony com Testcontainers

Testes de Integração no Symfony com Testcontainers

最後に、これほど簡単に、100% のカバー率など、とんでもないことを試すこともできます。信じられないですか? https://joubertredrat.github.io/symfony-testcontainers で自分で確認できます。

それでは、次回まで!

以上がTestcontainers を使用した Symfony の統合テストの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。