より広範なエコシステムのための Testcontainers for .NET モジュールを作成する方法

Testcontainers ライブラリを使用すると、実際の依存関係で単体テストを実行できるようにすることで、信頼性の高いテストを簡単に作成できます。 コンテナで実行されるものはすべて、データベースやメッセージブローカーからKubernetesクラスタやテスト用のクラウドソリューションまで、わずか数行のコードでテストの一部にすることができます。

柔軟なAPIと、自動クリーンアップやマッピングされたポートのランダム化など、細部にまでこだわったため、Testcontainersは広く採用されているソリューションになりました。 それでも、Testcontainersをさらに向上させるのは、モジュールのエコシステム、つまりコンテナを自分で構成することなく、特定のテクノロジーでアプリケーションをテストできる事前構成済みの抽象化です。

couchbase、mongodbなど、さまざまなテクノロジーのタイル張りのロゴ。

そして今、最近の Testcontainers for .NET リリースにより、モジュールのサポートがこれまで以上に強化されています。

この記事では、お気に入りのテクノロジ用に Testcontainers for .NET モジュールを作成する方法、一般的な構成オプションを API に追加するようにモジュールに機能を追加する方法、およびモジュールの適切な例を探す場所について説明します。

テストコンテナの作成方法。 より広範なエコシステムのためのネットモジュール

Testcontainers for .NET のモジュールを実装する方法

Testcontainers for .NET には、ユース ケースの複雑さに応じて、モジュールを実装する 2 つの方法が用意されています。 単純なモジュールの場合、開発者は ContainerBuilder クラスから継承できます。 これは、モジュールを構築し、必要に応じて構成する簡単な方法を提供します。

より高度なユース ケースでは、Testcontainers for .NET には、開発者 ContainerBuilder<TBuilderEntity, TContainerEntity, TConfigurationEntity>が . このクラスは、モジュールを構築するためのより柔軟で強力な方法を提供し、追加の機能と構成へのアクセスを提供します。

どちらのアプローチでも、開発者は構成とベスト プラクティスを共有して再利用できます。 また、コンテナをスピンアップするためのシンプルで一貫性のある方法でもあります。

Testcontainers for .NET リポジトリには、高度なモジュールをすばやくスキャフォールディングするための .NET テンプレート が含まれています。 新しいモジュールを作成して Testcontainers ソリューション ファイルに追加するには、リポジトリをチェックアウトし、最初に .NET テンプレートをインストールします。

git clone --branch develop [email protected]:testcontainers/testcontainers-dotnet.git
cd ./testcontainers-dotnet/
dotnet new --install ./src/Templates

次の CLI コマンドは、新しい PostgreSQL モジュールを作成し、ソリューション ファイルに追加します。

dotnet new tcm --name PostgreSql --official-module true --output ./src
dotnet sln add ./src/Testcontainers.PostgreSql/Testcontainers.PostgreSql.csproj

Testcontainers for .NET のモジュールは、通常、ビルダー、構成、およびコンテナーを表す 3 つのクラスで構成されます。 上記で作成したPostgreSQLモジュールはPostgreSqlBuilderPostgreSqlConfigurationPostgreSqlContainer

  1. ビルダークラスは、モジュールのデフォルト設定を設定し、検証します。 これは、Testcontainers ビルダーを拡張し、モジュールを構成するためにメンバーを追加またはオーバーライドします。 ビルダーは、有効な構成とコンテナー インスタンスを作成する責任があります。
  2. 構成クラスには、モジュールを構成し、コンテナーと対話するための省略可能なメンバーが格納されます。 通常、これらは a UsernamePassword など、後で必要になるプロパティです。
  3. 開発者はビルダーと最も対話します。 ライフサイクルを管理し、コンテナーと対話するためのモジュール固有のメンバーを提供します。 ビルダーの結果は、コンテナー クラスのインスタンスです。 

次の手順では、Testcontainers for .NET 用の新しいモジュールを作成するプロセスについて説明します。 まず、クラスによって ContainerBuilder 提供される既定の構成をオーバーライドして拡張する方法を示します。

その後、ビルダークラスと構成クラスに新しいメンバーを追加する方法を説明します。 これにより、ビルダーと構成の機能を拡張して、より複雑なユースケースをサポートできます。

モジュール構成の設定

Testcontainers for .NET の構成クラスは、不変になるように設計されています。 つまり、構成クラスのインスタンスが作成されると、その値は変更できません。 これにより、信頼性が高く、理解しやすくなり、A/Bテストなどの異なるユースケース間で共有しやすくなります。

PostgreSQL モジュールのデフォルト設定を設定するには、 のPostgreSqlBuilder読み取り専用DockerResourceConfigurationプロパティをオーバーライドし、両方のコンストラクタでその値を設定します。デフォルトのコンストラクタ DockerResourceConfiguration は の Init().DockerResourceConfiguration戻り値に設定されますが、オーバーロードされたプライベート コンストラクタは引数値を設定するだけです。 プロパティが変更されるとすぐに、不変の Docker リソース構成の更新されたインスタンスを受け取ります。 .NET テンプレートには既にこの構成が含まれているため、開発者は必要な部分をコメント アウトするだけで、すぐに作業を開始できます。

public PostgreSqlBuilder()
    : this(new PostgreSqlConfiguration())
{
    DockerResourceConfiguration = Init().DockerResourceConfiguration;
}

private PostgreSqlBuilder(PostgreSqlConfiguration resourceConfiguration)
    : base(resourceConfiguration)
{
    DockerResourceConfiguration = resourceConfiguration;
}

protected override PostgreSqlConfiguration DockerResourceConfiguration { get; }

PostgreSQL 構成を既定の Testcontainers 構成に追加するには、メンバー Init()をオーバーライドするか、コメント アウトします。 次に、Docker イメージや待機戦略など、必要な構成を基本実装に追加します。

protected override PostgreSqlBuilder Init()
{
    var waitStrategy = Wait.ForUnixContainer().UntilCommandIsCompleted("pg_isready");
    return base.Init().WithImage("postgres:15.1").WithPortBinding(5432, true).WithWaitStrategy(waitStrategy);
}

モジュール機能を追加する

PostgreSQL Dockerイメージを使用する場合、実行するためにパスワードを設定する必要があります。 新しいビルダー機能を追加する方法を示すために、この要件を例として使用します。

まず、クラスにPostgreSqlConfiguration新しいプロパティPasswordを追加します。次に、既定値が null のパスワード引数を既定のコンストラクターに追加します。

これにより、ビルダーは個々の引数または構成を設定できます。 オーバーロードされた PostgreSqlConfiguration(PostgreSqlConfiguration, PostgreSqlConfiguration) コンストラクタは、構成をマージします。 ビルダーは、すべての情報を含む更新されたインスタンスを受信して保持します。

public PostgreSqlConfiguration(string password = null)
{
    Password = password;
}

public PostgreSqlConfiguration(PostgreSqlConfiguration oldValue, PostgreSqlConfiguration newValue)
    : base(oldValue, newValue)
{
    Password = BuildConfiguration.Combine(oldValue.Password, newValue.Password);
}

public string Password { get; }

クラスが PostgreSqlConfiguration パスワード値を格納できるようになったので、メンバーを WithPassword(string) PostgreSqlBuilderに追加できます。 パスワードをインスタンスに PostgreSqlConfiguration 格納して、後でデータベース接続文字列を作成するだけではありません。 ただし、コンテナを実行するために必要な環境変数 POSTGRES_PASSWORD も設定します。

public PostgreSqlBuilder WithPassword(string password)
{
    return Merge(DockerResourceConfiguration, new PostgreSqlConfiguration(password: password)).WithEnvironment("POSTGRES_PASSWORD", password);
}

このアプローチに従うことで、 PostgreSqlContainer クラスは構成された値にアクセスできます。 これにより、データベース接続文字列の構築などの追加機能が開かれます。 これにより、このクラスは、モジュールを操作する開発者に対して、より合理的で便利なエクスペリエンスを提供できます。

public string GetConnectionString()
{
    var properties = new Dictionary<string, string>();
    properties.Add("Host", Hostname);
    properties.Add("Port", GetMappedPublicPort(5432).ToString());
    properties.Add("Database", "postgres");
    properties.Add("Username", "postgres");
    properties.Add("Password", _configuration.Password);
    return string.Join(";", properties.Select(property => string.Join("=", property.Key, property.Value)));
}

最後に、必要なパスワードが確実に提供されるようにするには、2 つの方法があります。 メンバーを Validate() オーバーライドし、不変の構成インスタンスを確認します。

protected override void Validate()
{
    base.Validate();

    _ = Guard.Argument(DockerResourceConfiguration.Password, nameof(PostgreSqlConfiguration.Password))
        .NotNull()
        .NotEmpty();
}

または、すでに行ったようにメンバーを拡張し Init() 、追加 WithPassword(Guid.NewGuid().ToString()) してデフォルト値を設定します。

両方のアプローチを追加することは常に良い考えです。 これにより、ユーザーは、モジュールが自分で、またはデフォルトで適切に構成されていることを確認できます。 これにより、ユーザーのエクスペリエンスに一貫性と信頼性を維持できます。 その後、社内または公開で独自のモジュールを作成するときに、他の開発者のロールモデルにもなることができます。

Testcontainers for .NET リポジトリは、Microsoft SQL Server モジュールのリファレンス実装を提供します。 このモジュールは包括的な例であり、 テストを含むモジュール全体の実装方法をよりよく理解するためのガイドとして役立ちます。

結論

Testcontainers for .NET は、テストの依存関係をスピンアップするための合理的で柔軟な方法を提供します。 新しいモジュールに .NET テンプレートを利用することで、開発者は既存の構成を利用し、カスタム抽象化で簡単に拡張できます。

これにより、わずか数行のコードでアプリケーションをテストできるテクノロジのエコシステムを拡張できます。 また、これは、公開するポートや、構成ファイルをコンテナに配置するためのパスを指定するなど、エンド開発者が低レベルの構成を行うことなく可能になります。

モジュールの優れたユース ケースには、お気に入りのデータベースやテクノロジをサポートするための Testcontainers for .NET プロジェクトへのパブリック コントリビューションや、同僚がベスト プラクティスに追いつくのに役立つ社内の抽象化が含まれます。

全体として、この記事で概説する手順に従うことで、Testcontainers for .NET の機能を簡単に拡張し、テストのセットアップを最大限に活用できます。

さらに詳しく