写し
そこで今日は、Testcontainersについて、そしてそれがローカル開発とテストを簡素化し、その結果として生産性を向上させるのにどのように役立つかについてお話しします。 私について少しだけ:私はアンナです。 私はここDockerのソリューションエンジニアです。 AtomicJarの買収に伴って参加しました。 これは、TestcontainersとTestcontainersクラウドの背後にある会社です。 私の専門知識を共有し、Testcontainersについてもっと話すことができてとてもうれしいです。 今日のセッションでは、テストが開発者の生産性にどのように影響するかについて説明します。 フィードバックループサイクルと日中の生産性向上との相関関係は何ですか? Testcontainersとは何か、それが何に使用されるのかを強調します。 また、デモでは、Kafka、PostgreSQL、Localstackをローカルにインストールせずに、Testcontainersモジュールを使用して実行する方法について説明します。 SeleniumモジュールでTestcontainersを使用してエンドツーエンドのテストを実行する方法と、TestcontainersクラウドとTestcontainersデスクトップとは何ですか。
目次
- 生産性を高めるものは何ですか? (1:29)
- 統合テストの課題 (6:43)
- Docker APIが選ばれる理由(11:24)
- Testcontainersの紹介 (12:14)
- デモ (19:20)
- デモ:統合(25:49)
- デモ:ローカル開発(33:50)
- デモ: ダッシュボード (44:03)
- 概要 (55:17)
- 詳細情報
生産性を高めるものは何ですか? (1:29)
ですから、先に進む前に、何があなたの生産性を動かし、何が日中の生産性を高めるのかを考えていただきたいと思います。 だから、考えてみてください。 私は実際に行われた研究に基づいた答えを持っています。 このように、生産性を高め、日々の仕事で生産性を高める3つの主要な項目があります。 まず、認知的負荷です。 つまり、例えば、コードエディタを開いて、変更を引っ張ってきて、タスクに応じていくつかの変更を加えたいと思ったら、コードが乱雑で、内部で何が起こっているのかを見て理解する必要があるということです。 ですから、各機能や各メソッドが何をしているのかを明確に理解するよりも、変更をどのように実装するかについて多くのことを考える必要があります。 そして、変更を実装します。 ですから、物事を処理するためには、追加の脳力が必要なのです。
もう一つ、生産性に大きな影響を与える2つ目の要素として、フィードバックサイクルがあります。 そして、ここでテストが重要になります。 つまり、コードに導入する変更が適切に機能し、期待どおりに動作する速度で反復できる速度、テスト速度がどれだけ速いかということです。 変更を実装してテストをローカルで実行し、変更に関するフィードバックをすぐに取得できるか、機能に関するフィードバックを取得するために 1 時間、場合によっては数時間、場合によっては数日待ってから本番環境に移行する必要がありますか。 テストはフィードバックループに大きく影響します。 そして最後になりましたが、フロー状態は、Slackのメッセージがポップアップ表示されたり、チームのメッセージがポップアップ表示されたり、誰かから電話がかかってきたり、メールを受け取ったり、テストで変更に関する結果が得られるまで長時間待たなければならないなど、タスクにどれだけ集中できるかを意味し、あるタスクから別のタスクに気を散らしてしまいます。 つまり、取り組んでいる1つのタスクに集中することができず、むしろ同時にさまざまなことに目を向けることになります。 そして、一日中、たくさんやったと感じますが、その結果がどうなったのか、結果がどうなったのか、はっきりしないのです。
ですから、生産性を高めることは難しく、フロー状態にあることも難しいのです。 ここには、フロー状態とフィードバックループがフロー状態にどのように影響するかについての記事へのリンクを貼っておきます。 そのため、頻繁にコンテキストを変更すると、フロー状態に到達できず、1つのことに集中してタスクを完全に終了し、別のタスクに移動することはできません。 これは、日中の生産性と一般的な勤務時間中の生産性に影響を与えます。 この研究から、 15 分から 30 分程度でフロー状態に到達できることがわかります。 したがって、たとえば、テスト結果が合格するのを待つ必要があり、過去のテストに関する結果を取得する必要がある場合、フロー状態に到達してタスクを完了することができます。 そしてその後、別のタスクに切り替えて、生産性を高め、仕事の日の後にこの数のタスクを完了したと言うことができます、すべてがうまくいった、これらの変更はすでに生産にあります。 私はとても素晴らしいです。 自分がやっていることに満足しています。 私はコードを書くのが大好きで、開発するのが大好きで、テスト結果を待ってから、あるタスクから別のタスクにコンテキストを切り替えるのではなく、別のタスクを開発してから別のテスト結果を待ちます。 これは良くないし、これは私たちを幸せにせず、開発の喜びを得ることを許さない。
統合テストの課題 (6:43)
では、何がフロー状態にプラスの影響を与え、何がフィードバックループにプラスの影響を与えるのでしょうか? 最も複雑な部分は統合テストであり、適切に行われれば、より迅速に反復し、このフロー状態に到達できます。 統合テストはどのように行われ、通常はさまざまな組織で行われていますか? 依存サービスをインストールしてアプリケーションをローカルでテストしたり、依存サービスをマシンにインストールしたり、postgresのインストールだけにしたりできます。 H2 データベースのようなインメモリソリューションを使用できますが、この場合、テストはローカルで成功する可能性がありますが、QA環境やデータベースの実際のインスタンスを含む本番環境に移動すると、インメモリソリューションでは実際のデータベースではないなどの実際のものではなく、これらのテクノロジーで異なる動作をするものがあるため、期待どおりに機能しないことがあります。
モックを使用する別の方法として、Wiremockを使用してモックを作成することもできますが、これも偽物であり、本番環境に進むにはいくつかの課題が生じる可能性があります。 統合テストを行う別の一般的な方法は、たとえばデータベースのインスタンスを共有することですが、課題は、テストを実行したいと仮定すると、いくつかのテストが失敗したことを確認し、コードで見つかったバグや類似性のためにテストが失敗したことが明らかでない場合があることです。 一部のデータ、一部のテストデータがデータベースにないため、別のチームが同じデータベースを使用して同じものをテストしていて、データを削除した可能性があります。 多くの場合、これらの不安定なテストのデバッグに時間を費やす必要があり、テストが失敗する理由を理解する必要があります。最悪の場合、バグのためではなく、不安定なテストデータが原因で失敗し、フィードバックループサイクルに再び影響します。 別の方法は、フィールドの方法と同様に、これは一般的に本番環境でのテストです。カナリアリリースでそれを行っている企業もありますが、これはすべての組織に適しているわけではなく、明らかに少しリスクがあります。
では、Dockerはこれにどのように役立つのでしょうか。 コンテナ化の進化に伴い、Dockerは、サービスをローカルで実行したり、CIでサービスを実行したり、自分のマシンやチームメイトのマシンでサービスを実行したりする機能をもたらし、すべてが同じように機能します。 つまり、同じデータベース、例えばpostgresをDockerから始めて、テストを実行し、このpostgresをアプリケーションで使用し、ローカルでテストを実行し、内部ループに焦点を当ててフィードバックを迅速に得ることができます。 しかし、ほとんどの場合、1つのサービスだけでなく、テスト用の環境、開発用の環境が必要であり、そのためにDocker Composeを使用できます。 アプリケーションを起動したり、複数のサービスを開始したり、同じpostgresの例で、この環境全体をアプリケーションと一緒にローカルに設定したり、テストを実行したり、手動検証を実行したりできます。 すべてが良いのですが、これはかなり静的なアプローチです。
次のイテレーションはDocker APIを使用しているので、YAMLファイルやDocker runコマンドからではなく、コードベースからpostgresを開始でき、postgres startのように、このpostgresのインスタンスが1つのテストにあり、別のテストでpostgresの別のインスタンスがあるとしたらどうでしょうか。 データベースを削除するだけで、別の陽性テストシナリオに影響を与える可能性があるいくつかのケースを確認します。
Docker APIが選ばれる理由(11:24)
そのため、Docker API を使用すると、ローカル環境をスピンアップするのに非常に役立つ場合があります。 なぜそうなのでしょうか? IDEを離れる必要はありません。アプリケーション・コードを開発するIDE内にとどまり、アプリケーション開発に使用されるのと同じ言語を使用してプログラムで環境を定義できます。 このようにして、環境を自己完結型にすることができ、あるアプリケーションから別のアプリケーションにコンテキストを切り替えることなく、開発に明確に集中でき、他のサービスをインストールする必要もありません。 したがって、必要なのは、プログラムAPIを使用して記述したコンテナを実行するためのIDE、コードベースベースのアプリケーション、およびDockerだけです。
Testcontainersの紹介 (12:14)
これがTestcontainersがどのようにして作成され、生まれたかです。 Testcontainersは、Docker APIに基づくオープンソースライブラリであり、データベース、メッセージブローカー、クラウドプロバイダーなど、Dockerコンテナで実行できるすべてのものなど、実際のサービスの一時的で軽量なインスタンスを提供します。 これはRedisの例ですので、Redisを起動することをプログラムで定義し、使用するイメージ、公開するポートを定義し、コードベースにRedisがあります。
それはどのように機能しますか? 同じRedisの例を、IDEで定義します。 したがって、基本的には、Dockerの実行、Redisイメージのポート、必要なもの、Redisの起動方法のコード宣言で定義するものは何でも実行します。 すべてがDockerコマンドに変換され、ローカルホスト上のDockerデーモンによって実行されます。 デーモンはイメージをプルし、コンテナを起動して、接続の詳細をIDEに提供します。 したがって、プログラムでコンテナを開始し、同じ方法でプログラムでコンテナを管理したり、ホストを取得したり、ポートを取得したり、環境変数を取得したりできます。 したがって、この情報を静的に定義する必要はなく、コンテナが実行されているホストとポートに関するこの情報を覚えておく必要はなく、Testcontainers で開始されたコンテナからこの情報を動的に取得できます。
つまり、テスト環境を自動的に管理できるということです。 テスト開始前に、コンテナが起動されるため、統合テストの環境全体が準備されます。 その後、テストが実行され、Testcontainersで定義したサービスが使用され、テストが完了した後、コンテナはTestcontainersリソースリーパーによって自動的に破棄され、テスト環境を自動的に維持および管理するのに役立ちます。 したがって、DockerComposeと比較します。 Docker Composeでは、手動でDocker Composeを開始し、Docker Composeをダウンと言います。Testcontainersを使用すると、これはすべてryukコンテナによって行われ、開始するコンテナを定義するだけで済みます。
そして、このように、内側のループに集中することができ、テストにとどまることができます。 内側のループでは、通常は統合テストの段階で外側のループでテストされる多くのことをテストできます。 したがって、通常外側のループで実行される統合テストの約 80%は、内側のループに移動して、テストスーツの重さに応じて、コードの変更に関するフィードバックを1秒または数分で取得できます。場合によっては数時間かかることもあるすべてのテストが実行されるプッシュを待つのではなく、テストスーツの重さによって異なります。
さて、Testcontainersの使用状況に関する統計を少しご紹介します。 現在、Docker HubからのTestcontainersイメージが 13 00万個以上あることがわかります。 2000以上の組織がそれを使用しており、10以上の言語をサポートしていますが、言語サポートについては後で説明します。また、Spotify、Netflix、Elasticからは、統合テストのためのTestcontainersの使用例や、開発ループの高速化、ユニットテストのような統合テストのようなローカル統合テストでのイテレーションの高速化方法について、多くの公開ケースやブログ記事を見つけることができます。
これは、サポートする言語の概要です。 現在私たちが持っている最高のサポートは、Java、.net、 Node、Python、Goです。 他の言語は主にコミュニティでサポートされていますが、Docker のコアメンテナーもこの言語の実装を確認し、言語のメンテナンスと新しいモジュールの作成を支援します。 ここではC++は入れませんでしたが、C++用のTestcontainersライブラリの実装もあります。
これは、汎用コンテナを使用してJavaでRedisを実行する方法の例です。 また、.net の同様の例 また、2行のコードのように、しかしここでは、汎用コンテナではなくRedisビルダーを使用していることを強調していることがわかります。 それはどういう意味ですか。 つまり、モジュールがあるということで、現在ではさまざまな言語用のモジュールが 100 以上あり、モジュールは特定のテクノロジーに関する高レベルの抽象化です。 例えば、クロマやダッパーなど、Testcontainersでサービスを開始する方法を深く掘り下げる必要はありませんが、この特定のサービスを開始するために必要な基本設定を定義するモジュールを使用することができます。したがって、このモジュールを依存関係としてプロジェクトに含めるなど、名前を指定するだけです。 イメージ名(「Start」など)を入力すると、開始されます。 一部の環境変数の開始方法を変更する必要がある場合は、同じモジュールを使用してこれを行うことができます。
デモ:開始中 (19:20)
この時点で、デモ部分に進みましょう。 したがって、1つの簡単な例から始めることができます。 Redisを起動する方法の一般的なコンテナ。 それでは、まずpom XMLファイルに移りましょう。 したがって、もう一度強調すると、Testcontainersはライブラリです。これはオープンソースのライブラリです。 あなたが始めるために必要なすべては、依存関係を追加する必要があります(私はMavenを使用しているので、私の場合はpom XML依存関係)TestcontainersJupiterがpostgresを使用するのを参照してください。 これは、使用したいテクノロジーと組み合わせることができるモジュールです。一般的なTestcontainersのものを使用し、here、postgres、Kafka、localstack、Seleniumなどのモジュールを追加できるため、これらのモジュールはすべてデモプロジェクトで使用されます。 大丈夫です。 ここから本題に戻りましょう。 ここで、Redisのバージョンを定義し、公開したいポートを言うので、Redisに接続するためにこのポートを公開する必要があります。開始すると、コンテナからホストを取得できるように接続URLを確認できます。 ハードコーディングする必要はなく、動的に提供されます。 私が取得できる最高のことは、Redisの公開されたポートにマップされたポート、つまり、ポートをハードコーディングする必要がないことを意味します。 テストを並行して実行し、Redis の 1 つのバージョンだけでなく、複数のバージョンの Redis を使用する場合、Testcontainers は各コンテナーをランダムなポートで開始するため、ポートの競合について心配する必要はありません。私は私のシステムでどのポートが使用されているかを覚えておく必要はありません、私はただ私のコンテナを起動するためにTestcontainersと言うと、すべてがライブラリによって管理されます。
では、実行してみましょう。 ここでは、Docker デスクトップを使用してコンテナを起動することがわかります。私はすでに事前に引っ張られたイメージを持っているので、ここでコンテナを作成して開始しています。 これは1ミリ秒でかなり速く、統合テストでこのRedisインスタンスに接続するためにさらに使用できる接続URLがあります。 また、ポートがあったことを確認し 50103 もう一度実行してみましょう。 さて、別のポートがあるので、新しいコンテナを起動するたびに、ホストマシンで使用可能なランダムなポートで開始されます。 もう少し高度な使用法を示しましょう。私はそれを少し速くするためのコードをここに持っています。 したがって、Testcontainersを使用してネットワークを使用することもできるため、実際には、Dockerを使用するのと同じ方法、またはDocker Composeで物事を記述するのと同じ方法でTestcontainersを使用できますが、プログラムで行うことができます。 Docker APIで利用可能なものはすべてTestcontainersで使用できるため、ネットワーキングは、1つのネットワーク内でDockerを使用してコンテナを開始できるものの1つであり、Testcontainersでも同じことができます。 ここでは、ネットワークを定義します。私はカフカコンテナの外部Zookeeperの例を持っているので、ここではZookeeperを定義するか、Zookeeperの別のインスタンスを使用してこのKafkaに接続することができますが、ネットワークの例では、両方を起動しましょう。 このネットワーク内で開始する予定の zookeeper のバージョンのみを提供できます。 このネットワークがどこにあるか、環境、または開始した zookeeper ポート。 次に、Kafkaでも、外部のZookeeperとのネットワークで開始するKafkaのイメージを定義します。これはポート 2181 で実行されているもので、開始します。 次に、すべてが正しく開始されたことを確認するために、getBootstrapServers();Kafkaが正常に起動されると、このリンクが表示されます。 では、この例をもう一度実行してみましょう、実際にはRedisをもう一度起動します。 また、Docker Desktop では、コンテナが開始されていることも確認できます。 現在、Kafkaはzookeeperに接続されており、コンテナは自動的に破棄されるため、コンテナ管理では何もしていません。これはTestcontainersによって私のために行われます。
そして、ここにKafkaブートストラップサーバーのURLがあるので、このセットアップが正しく開始され、コンテナが1つのネットワーク内で開始されたことを意味します。 Docker Composeで同じことを行うと、保守が難しくなります。 これは数行の設定にすぎませんが、より包括的な例に取り組んでいる場合は、ここでさらに多くの行を行います。 これは単純なデモです。
デモ:統合(25:49)
さっそく前に進みましょう。 したがって、これらのコンテナはそれ自体で開始されたばかりで、アプリケーションと対話していませんが、アプリケーションがこれらのコンテナの一部と通信したい場合はどうなりますか? アプリケーションをこのコンテナと環境をスタンドアロンのものだけでなく、開発サイクルと組み合わせて開始したい場合はどうすればよいですか? そこで、これを行う方法の例を次に示します。実はまず、ここの図にお進みください。 デモアプリケーション用に、カタログサービスの開発に焦点を当てたSpringbootプロジェクトを作成したので、これが開発中のアプリケーションです。 製品データをPostgreSQLデータベースに保存し、製品画像をAWS S3に保存し、Kafkaを使用して画像のアップロードのイベントをリッスンします。 また、在庫サービスにも依存するため、製品に関する情報を表示し、在庫に何かがあるかどうかを理解したい場合、アプリケーションは在庫サービスと通信しています。 それをローカルで実行し、ローカルでテストするには、すべてのサービスをどこかで実行する必要があります。 Docker Composeファイルのように、どのように開始したいかを定義できるようなものです。 共有インスタンスを持つステージング環境を持つことも、Testcontainersを使用してすべてのサービスを起動し、ローカル環境として実行される本番環境のようなサービスの実際のインスタンスとしてオンデマンドで持つこともできます。
では、どうすればいいのでしょうか? したがって、これはTestcontainersで開始するサービスを定義するためのコンテナ構成クラスです。 ここで重要なことは、アプリケーションがテストモードで起動したときにSpringbootアプリケーションにサービスに接続するように指示するために、サービスの説明の上にServiceConnectionアノテーションを存在として定義する必要があるということです。 このアノテーションは、 springboot 3以降で使用できます。1 、これは、Springbootチームによって開発されたTestcontainersとSpringbootの特別な統合のようなものです。 彼らは、統合テストのためにTestcontainersを実行することを推奨しており、Springbootアプリケーションのこのテスト方法をどのように開始できるかについて多くのガイダンスを提供しています。 したがって、このアノテーションはすべてのコンテナで使用できるわけではありません。 現在最も人気のあるものについては、localstackでも利用できると思いますが、Testcontainersベースのコンテナを起動してアプリケーションに接続するさまざまな方法を示すために、古いファッションの説明をここに残しました。 私が使用しているプログラムpostgres:16、最新のものではありませんが、それでもこれが私の製品版であるとしましょう。 私はKafkaを使用しています-これは、Testcontainersを使用してKafkaを定義する方法のようなものです。 繰り返しになりますが、これはTestcontainersモジュールです。汎用コンテナですべてを実行することも、モジュールを使用することもできます。 モジュールの実装に進むと、汎用コンテナが拡張されていることがわかります。つまり、社内のソリューションを使用している場合、Confluentのものとは異なる社内のKafkaを使用していることがわかります。 独自のモジュールを定義することも、汎用コンテナを拡張し、必要なメソッドを実装し、社内のKafkaモジュールを統合テストに使用することもできます。 ライブラリとしてパックし、開発チーム全体に分散させることができるので、誰もがそれをpom XMLにライブラリとして追加したり、使用しているGradleやその他のビルダーをビルドしたりできます。
さらにスクロールして実装すると、Kafkaポート、zookeeper、zookeeperの起動方法、Kafkaへの接続方法などのデフォルトのパラメーターが表示されるため、心配する必要はありません。 新しいKafkaモジュールと言って、使用したいKafkaバージョンのイメージを入れるだけで、ここにあるものはすべてすでに実装されています。 先に進むには、LocalStack-ここでは動的プロパティレジストリを使用してアプリケーションプロパティにlocalstack変数を追加しているので、基本的にはアクセスキー、シークレットキー、リージョン、エンドポイントを取得する必要があります-これは、ローカルスタックに接続するためにアプリケーションプロパティに追加する必要がある基本的なものです。 より多くの構成が必要な場合は、それを行うことができますので、ここで何があるかを確認しましょう。 コンテナのID、境界、名前、環境、ホストなどを取得できます。 localstackでできることはたくさんありますが、localstackだけでなく、コンテナから物事を取得するために使用できる非常に豊富なプログラムAPIがあります。
さて、この実装では、localstackコンテナを起動してからS3 バケットを作成し、ここでは、インベントリサービスのモックまたは高度なモックのようなものとして機能するMicrocksコンテナも使用しています。 オープンAPI仕様を使用しているため、チームでオープンAPIやgraphQLを使用している場合は、私の場合はインベントリサービスの実装を担当するチームにこのファイルを要求できます。 このファイルのテストデータを更新し、プロキシコンテナを使用してオープンAPIに基づいてサービスを実行すると、コントラクトテストも行えるため、インフラストラクチャの小さな部分をローカルで実行し、他のチームが開発しているサービスを含めることができます。 そのため、特定のサービスがデータベースだけでなく、別のチームが開発しているマイクロサービスなど、別のサービスと通信している方法を確認し、マイクロサービスが適切に機能していることを確認したいと考えています。
デモ:ローカル開発(33:50)
では、サービスを使用してアプリケーションをローカルで起動したい場合はどうすればよいですか? テストクラスパスの下でメインクラスを定義し、コンテナ設定を使用してメインからアプリケーションを起動したいと言い、ただ開始することができます。 これが、Docker Desktopを開いてコンテナのステータスを確認することもできる理由です。 ここでは、Java だけでなく、すべての言語のすべての Testcontainers ライブラリ実装で使用されるデフォルトのコンテナである ryuk コンテナがあることがわかります。 これはリソースリーパーです。コンテナを監視し、テストサイクルの完了後にコンテナを削除します。 したがって、ここではKafkaが準備ができており、ローカルスタックであることがわかります。これはMicrocks、Postgresで使用され、私のアプリケーションが起動されたようです。 localhost:8080に行くことができます。 はい、これは私のアプリケーションです。 ここに画像をアップロードできます。 さて、アップロードされました。 ええ、そしてそれが変わったのがわかります。 したがって、状態を更新しても、イメージがデータベース内にあることを意味します。 また、たとえば、postgresデータベースに移動してデバッグすることもできます。 それでは、データベースに接続してみましょう。 だから私は私のpostgresコンテナの中にいます。 説明したテスト対象のデータベースに接続しました。 これは、Testcontainersでpostgresコンテナを起動したときのデフォルトユーザーであり、製品テーブルから画像を選択できます。 そして、ここでは、すべての統合が適切に機能したことを意味する画像がアップロードされています。カフカがイベントをリッスンし、S3にアップロードされた画像、すべてが順調です。 たとえば、Kafkaのログも確認できます。 そのため、イベントに関する情報があります。
したがって、この場合、アプリケーションを実行し、手動でテストし、完了したら停止することができます。 そして、見てみましょう。 はい、コンテナは破壊されます。 手動で管理する必要はありません。 すべてがあなたのために管理されます。 同じテスト構成を統合テストで再利用できます。 そのため、基本の統合テストを定義し、Testcontainersの設定をインポートできます。 その後、テスト実装で、この基本統合テストクラスを拡張でき、再度、このテストサイクルでコンテナが開始され、コンテナは自動的に破棄されます。 また、ここではテストデータについて、テストデータを追加するSpringbootの方法を使用しています。 私は自分のリソースにテストデータSQLファイルを持っています、そしてここでは私はちょうど私のデータベースにデータを入れるためにspringbootのSQL注釈を使用しています、そしてspringbootとTestcontainersの非常に良好で緊密な統合のために、これはかなり簡単です。 Testcontainersを使用していることはすでに知っていますが、このテストデータ情報をTestcontainersで開始されたデータベースに入れます。 したがって、このテストでは、私が行うことは、いくつかの簡単な検証のように、製品を正常に作成できます。 商品画像を正常にアップロードすることができます。 したがって、画像を取得し、APIを呼び出して画像をアップロードし、これが製品リストに存在し、実際にS3にアップロードされたことを確認します。 APIを呼び出すことで、再度コードで製品を取得できます。 そして、open APIの確認を確認すると、オープンAPIの仕様に基づいて、開始したインベントリサービスで私のサービスが正しく動作することを確認しました。 ええ、そしていくつかの陰性テストで実際に実行できるようにしました。 テストが開始され、再びコンテナがDockerデスクトップに存在することがわかります。 したがって、テストサイクルの前に開始され、その後自動的に破棄されます。 多くの場合、テストの前にコンテナの準備ができていることを確認して、まだ適切に開始されていないサービスに対してテストが実行されていないことを確認する方法についての質問があります。 Testcontainers には、モジュールにデフォルトで実装される待機戦略があり、汎用コンテナーを使用すると、独自の待機戦略を実装できます。 そのため、ログなどを待つことができます。 繰り返しになりますが、テストが完了し、コンテナが破壊されたことがわかります。 私は、この非常に包括的なインフラストラクチャを使用して、アプリケーションのAPIエンドポイントを呼び出すいくつかのテストを実行するだけです。 また、リソースを管理する必要もありません。
待機戦略に戻るには、多くの待機戦略があります。 ログを待つことができます。 ヘルスチェックを待つことができます。 Docker の compose ファイルの場合と同じです。 そのため、コンテナのヘルスチェックも同じ方法で定義できます。 モジュールを使用している場合は、モジュールがすでに待機戦略を実装しており、コンテナが起動し、この事前定義された環境に対してテストを実行する準備ができていることを確認するための可能な方法を考える必要がないため、モジュールを使用することをお勧めします。 もう一つ、今日お見せしたいのは、この小さなドロップダウンです。 これはTestcontainersデスクトップアプリケーションであり、ここでは最初にランタイムを定義できます。 たとえば、今はDocker Desktopを使用してローカルでコンテナを実行していましたが、Testcontainers Cloudを使用して実行することもできます。 また、ここではコンテナを凍結してシャットダウンすることができます。 この機能ともう一つ便利なものを実際に選択してみましょう。 一部のサービスをサービスとして定義できます。 つまり、Testcontainersは、これまで見てきたように、ランダムなポートでコンテナを起動します。 データベースへの静的接続が必要な場合、たとえば、ログやDockerデスクトップ、またはTestcontainersクラウドでどのポートが使用されているかを確認し、データベースへの文字列接続を更新してデータベースの内部で何が起こっているかを確認するのは望ましくありません。 静的接続文字列として定義できます。 また、postgresは静的ポートで実行されるため、毎回接続できます。 では、もう一度テストを実行してみましょう。 今回はTestcontainers Cloudで実行します。 また、コンテナの凍結シャットダウンを有効にしました。 そのため、コンテナはしばらくの間、またはコンテナを解凍しない限り破壊されません。 これは、デバッグ目的で非常に便利な機能です。 一部のテストが失敗していることがわかり、その理由を理解したい場合は、コンテナを凍結してから続行に移動し、ログを確認して何が起こっているかを確認できます。 また、ここでは、コンテナのステータス、開始されたコンテナ、ターミナルを開くことができる、ログを取ることができる、そしてここにKafkaコンテナのログが表示されます。 また、現在、このKafkaコンテナはクラウドで実行されています。 したがって、Testcontainers Cloudで実行されているときにこのコンテナに接続するのは非常に簡単な方法です。
デモ: ダッシュボード (44:03)
ここでダッシュボードに移動しましょう。 はい、Testcontainersクラウドのもう一つの利点はダッシュボードです。両方のローカル セッションを表示できます。 Docker Desktopで実行しているのが私のセッションでした。 ここではそれを強調しています。 つまり、コンテナ、すべてのコンテナが開始するのにかかる時間、およびコンテナがどれだけの時間を費やしたかが表示されます。 このセッションの前に実験していた小さなテストセッションのようなものがわかります。 このライブセッションは、現在実行中のテストとともに見ることができます。 リモートワーカーとつながることができます。 これがクラウドVMです。 docker psを実行すると、すべてのコンテナが実際に起動されていることを確認できます。 そして、はい、実際にはすべてのテストが完了しています。 しかし、もう一度docker psを実行すると、すべてのコンテナがまだそこにあることがわかります。 解凍していきましょう。 さて、コンテナは終了しました。 また、docker psを実行すると、コンテナは残りません。 したがって、テストは完了します。 そして、これがクラウドソリューションのもう一つの利点です。 たとえば、ローカル リソースが不足している場合は、クラウドでコンテナーを実行できます。 ここでも、アプリケーションはローカルで実行され、テストはローカルで実行されますが、コンテナはクラウドで開始されます。 また、TestcontainersベースのテストをCIパイプラインワークフローと統合し、CIでテストを実行する場合にも非常に便利です。 そこで、CI で Testcontainers Cloud を使用してテストを実行する方法の例を次に示します。 これは、Testcontainers Cloud エージェントをダウンロードし、サービス アカウントのシークレット トークンを提供する 1 つの手順にすぎません。 他のすべては同じです。 このアプローチは、Kubernetes上で実行されるCIツールにとって非常に便利で、たとえば、Kubernetes上でJenkinsを実行し、各ワーカーがコンテナとして起動した場合、Testcontainersテストを実行するにはこのコンテナ内にDockerをインストールする必要があります。なぜなら、それらはDocker APIに基づいており、Dockerコンテキストが利用可能である必要があるからです。 したがって、セキュリティチームが承認できないDockerでDockerを使用してこれらすべての操作を行うのではなく、セキュリティオーディションに合格しないこともあります。 Testcontainersクラウドは、CIプロバイダーごとに1行で使用でき、TestcontainersベースのテストにこのリモートDockerコンテキストを持つことができます。 したがって、彼らはクラウドで実行され、すべてがそこにあります。 これらは、テストサイクルの完了後に破棄されます。 つまり、このオンデマンドリソースがプロジェクトで管理され、組織全体や複数の製品間でTestcontainersの使用を拡大するのに役立ちます。
それでは、最後の例をお見せしましょう。 Seleniumテストと実際にコメントを追加し、これらの変更をCIにコミットして、CIでテストがどのように実行されていたか、そしてそこでSeleniumテストがどのように実行されたかを見てみましょう。 この構成がどのように行われたかについて少し説明してください。 したがって、Testcontainersを使用してアプリケーションに対してエンドツーエンドのテストを実行する場合、このspringbootの例では、イメージにパッケージ化する必要さえありません。 アプリケーションを実行し、ローカルホストに対してSeleniumテストをナビゲートし、いくつかのシナリオを実行できます。 ここでは、Firefoxを使用してSeleniumコンテナを起動しています。 テストを記録できます。 私はすべてを記録していますが、たとえば失敗を録音することができます。 テスト記録を保存するターゲットを指定します。 プロジェクトフォルダだけでなく、他のフォルダでもかまいません。 録音の形式を指定できます。 そしてここで重要なのは、このURLをドライバーに接続して接続すると言うことです。 これは、ローカルホストを表すTestcontainersのURLです。 そして、これはほぼそれです。 そこで、Firefoxのコンテナピースを起動し、Webブラウザ、Testcontainersによるドライバコンテナの提供を入れます。 次に、このFirefoxコンテナからSeleniumアドレスを使用してリモートドライバーを作成します。 そして、ローカルホストで実行されているアプリケーションに接続します。 これにより、ローカルまたはCIでテストを簡単に実行でき、ユニットテストから始まり、エンドツーエンドのSeleniumヘビーテストで終わるさまざまなタイプのテストを実行できます。 これらの変更をコミットしてからコメントします。 したがって、このクラウドワーカーのセッションが終了していることがわかります。 これは、セッションの期間についてよく聞かれる質問の1つでもあります。 コンテナを実行していない場合、セッションはアイドル期間から 30 分以内に終了します。 そのため、リソースはかなり効率的に管理されます。 クラウドリソースを使用していない場合、それらは破壊されるだけです。 だから、このプロジェクトではなく、ここです。
さて、これがトリガーされたCIジョブであることがわかります。 そして、まもなくここにいくつかのコンテナがオープンする予定です。 私は実際にそれを更新することができます、そしておそらくもっと多くのコンテナがあるでしょう。 では、さっそく始めましょう。 したがって、テストケースで使用されるすべてのコンテナ。 そして、CIはセッション内に表示されます。 何度か積み込んでみて、すぐにここにコンテナが入るよ。 まだ来ていません。 プロジェクトを確認しましょう。 さて、それはまだ構築中です。 ですから、ここでセッションがあるはずです。 はいどうぞ。 また、ここからはどのようなコンテナが使われているかも確認できます。 どのワークフローがそれをトリガーしたかを確認できます。 ですから、基本的には今チェックすべきことは同じです。 だからあなたはそれのステータスを見ることができます。 どのプロジェクトがそれをトリガーしたかを確認できます。 したがって、複数のプロジェクトで使用している場合は、タグを付けるだけで済みます。 また、どのプロジェクトがどのバージョンのコンテナを使用しているか、どのバージョンのイメージを使用しているかを明確に把握できます。 したがって、テストに使用されたイメージバージョン間で一貫性があるかどうかを理解し、場合によってはそれが非常に重要です。 さて、ここでは、開始されたコンテナとテストがまだ実行されているコンテナを確認できます。 ええ、実はSeleniumのテストは始まったばかりです。 だから、Firefoxコンテナがビルドされ、Firefoxのイメージが引っ張られて起動していることがわかります。 そのため、数秒でダッシュボードに表示されます。 はい、ここにあります。 したがって、テストが完了すると、ここにステータスが表示されます。 また、このワーカーはすでに切断されています。 私の設定では、GitHub Actionsの統合を使用しましたが、別のCIプロバイダーを使用している場合です。 CircleCI、Tekton、Jenkins の例があります。 これは、サービスアカウントを追加して作成し、その資格情報をプロビジョニングするために必要なステップの1つにすぎず、CIでTestcontainersテストを実行することから始める方法とほぼ同じです。 さて、テストは完了したようです。 はい、Seleniumを含むすべてのテストが完了しています。 彼らは合格しましたか。 はい、セッションでは、コンテナが破棄されたことがわかります。 彼らはもう走っていません。 したがって、リソースの無駄はありません。
概要 (55:17)
大丈夫です。 まとめましょう。 Testcontainersを使い始めた人が今でも尋ねる最も一般的な質問は、「Docker Composeとの違いは何ですか」または「Docker Composeを使用しているのに、なぜTestcontainersを代替手段として検討する必要があるのですか」です。 Docker Compose は素晴らしいです。 また、アプリケーションから開始する静的サービスを定義し、開発中に確認することで、ローカル開発に最も価値を提供します。 しかし、Testcontainersはテスト目的で設計されています。 そのため、Docker Compose では、テストを並行して実行し、並行して実行されているテストの安定したインフラストラクチャを維持することが難しくなります。 Testcontainersはランダムなポートでコンテナを実行するため、ポートの競合を心配する必要はもうありません。 必要な数のコンテナを実行できます。 IDE内にとどまります。 Docker Compose で開始するコンテナを記述するために、YAML 形式や TOML 形式を学習する必要はありません。 Testcontainers の場合は、自分が知っているプログラミング言語で環境を記述します。 また、APIまたはTestcontainersライブラリを使用して、このインフラストラクチャを実行および管理するだけです。
要約すると、Testcontainersはテスト、特に並列テストや統合テスト目的の動的環境プロビジョニングに最適です。 Docker Composeは、ローカル開発のためだけに、または静的環境のような環境をあるマシンから別のローカルに移動してステージングしたい場合に最適ですが、繰り返しになりますが、これは静的であり、維持するには、この環境を手動で実行して停止するか、すべてを管理する代替ソリューションがすでにある場合は、自動的にそれを行うスクリプトを追加する必要があります。 Testcontainers Cloudは、Macでテストを実行する場合でも、同僚がWindowsを使用している場合でも、パイプラインでKubernetesでJenkinsを実行している場合でも、環境の問題によるテストの不安定さを解決する必要はありません。 コンテナのランタイムは 1 つだけで、テストを実行する環境に関係なく、コンテナは同じ一意の環境を使用するため、これらのテストの実行に問題はありません。 繰り返しになりますが、ローカルのユースケースでは、Docker Desktop を使用して Testcontainers テストを実行できます。 主な要件は、TestcontainersテストでDockerコンテキストを利用できるようにすることです。なぜなら、彼らはDocker APIを使用しているため、Dockerが必要なからです。 これも、GitLab CIでテストを実行する方法の一例です。 GitHub Actionsと非常によく似ており、Jenkinsと非常によく似ていますが、ワークフローに1つのステップを追加するだけです。 Playwright for NodeまたはJavaを使用してエンドツーエンドのテストを再度開始する方法に関する役立つリンクがいくつかあります。 Seleniumや他のモジュールでの統合テストではなく、エンドツーエンドのテストを行いたい場合は、TestcontainersのWebサイトにアクセスして、実際にモジュールを確認できます。 私がウェブサイトやモジュールのページに行くと、ここで、言語別、タイプ別にソートされた、多くのモジュールが開始するための非常に簡単な方法を見ることができます。 そう、今日はこれでおしまいです。 ありがとうございました。 ご不明な点がございましたら、お気軽にお問い合わせください。 ありがとうございます。
さらに詳しく
- ドッカーは初めてですか? 始めましょう。
- 無料のラーニングパスでDocker製品を深く掘り下げます。
- Docker Newsletter を購読してください。
- Docker デスクトップの最新リリースを入手します。
- 質問がありますか? Docker コミュニティがお手伝いします。