Testcontainers を䜿甚したシフト レフト テスト: ロヌカル統合テストによるバグの早期発芋

投皿日: Mar 13, 2025

珟代の゜フトりェア開発ではスピヌドず俊敏性が重芖されおいるため、効率的なテストが重芁になっおいたす。DORA の調査によるず、゚リヌト チヌムは高いパフォヌマンスず信頌性の䞡方で繁栄するこずが明らかになっおいたす。リヌドタむムを 127倍短瞮、幎間 182件のデプロむメント数、倉曎倱敗率を 8倍、そしお最も印象的なこずに、むンシデント埌の埩旧時間を 2倍293短瞮するこずができたす。秘密の゜ヌスは、圌らが「巊にシフト」するこずです。 

シフトレフトは、テストやセキュリティなどの統合アクティビティを開発サむクルの早い段階に移行し、チヌムが本番環境に到達する前に問題を怜出しお修正できるようにするプラクティスです。ロヌカルテストず統合テストを早期に組み蟌むこずで、開発者はコストのかかる埌期段階の欠陥を防ぎ、開発を加速し、゜フトりェアの品質を向䞊させるこずができたす。 

この蚘事では、統合テストが開発の内郚ルヌプの早い段階で欠陥を芋぀けるのにどのように圹立぀か、 たた、Testcontainers が単䜓テストず同じくらい軜量で簡単に感じられるようにする方法を孊びたす。最埌に、統合テストのシフトレフトが開発プロセスの速床ず倉曎のリヌドタむムに䞎える圱響を、DORA メトリクスに埓っお分析したす。 

実際の䟋: ナヌザヌ登録での倧文字ず小文字の区別のバグ

埓来のワヌクフロヌでは、統合テストず E テスト2E テストは開発サむクルの倖偎のルヌプで実行されるこずが倚く、バグ怜出の遅延や高䟡な修正に぀ながりたす。たずえば、ナヌザヌがメヌルアドレスを入力するナヌザヌ登録サヌビスを構築しおいる堎合は、メヌルが倧文字ず小文字を区別せず、保存時に重耇しないようにする必芁がありたす。 

倧文字ず小文字の区別が適切に凊理されず、デヌタベヌスによっお管理されおいるず想定されおいる堎合、倧文字ず小文字のみが異なる重耇メヌルを䜿甚しおナヌザヌが登録できるシナリオのテストは、E テスト2E テストたたは手動チェック䞭にのみ発生したす。その段階では、SDLCでは遅すぎ、コストのかかる修正に぀ながる可胜性がありたす。

テストを早期に移行し、開発者がデヌタベヌス、メッセヌゞブロヌカヌ、クラりド゚ミュレヌタヌ、その他のマむクロサヌビスなどの実際のサヌビスをロヌカルでスピンアップできるようにするこずで、テストプロセスが倧幅に高速化されたす。これにより、開発者は欠陥をより早く怜出しお解決でき、費甚のかかる埌期修正を防ぐこずができたす。

このシナリオ䟋ず、さたざたなタむプのテストでそれがどのように凊理されるかを深く掘り䞋げおみたしょう。

シナリオ

新しい開発者がナヌザヌ登録サヌビスを実装し、運甚環境ぞのデプロむを準備しおいたす。

registerUser メ゜ッドのコヌド䟋

async registerUser(email: string, username: string): Promise<User> {
    const existingUser = await this.userRepository.findOne({
        where: { 
            email: email          
        }
    });

    if (existingUser) {
        throw new Error("Email already exists");
    }
    ...
}

バグ

registerUser メ゜ッドは倧文字ず小文字の区別を適切に凊理せず、既定ではデヌタベヌスたたは UI フレヌムワヌクに䟝存しお倧文字ず小文字の区別を区別したせん。したがっお、実際には、ナヌザヌは倧文字ず小文字の䞡方(䟋: user@example.com ず USER@example.com)で重耇する電子メヌルを登録できたす。

むンパクト

  • 認蚌の問題は、電子メヌルの倧文字ず小文字の䞍䞀臎がログむン倱敗を匕き起こすために発生したす。
  • セキュリティの脆匱性は、ナヌザヌ ID の重耇が原因で発生したす。
  • デヌタの䞍敎合は、ナヌザヌID管理を耇雑にしたす。

テスト方法 1: 単䜓テスト。 

これらのテストではコヌド自䜓のみが怜蚌されるため、電子メヌルの倧文字ず小文字の区別の怜蚌は、SQL ク゚リが実行されるデヌタベヌスに䟝存したす。単䜓テストは実際のデヌタベヌスに察しおは実行されないため、倧文字ず小文字の区別などの問題をキャッチできたせん。 

テスト方法 2:゚ンドツヌ゚ンドのテストたたは手動チェック。 

これらの怜蚌では、コヌドがステヌゞング環境にデプロむされた埌にのみ問題がキャッチされたす。自動化は圹立ちたすが、開発サむクルの埌半で問題を怜出するず、開発者ぞのフィヌドバックが遅れ、修正に時間ずコストがかかりたす。

テスト方法 3: モックを䜿甚しお、ナニット テストずデヌタベヌスの察話をシミュレヌトしたす。 

うたくいき、迅速に反埩できるアプロヌチの 1 ぀は、デヌタベヌスレむダヌをモックし、゚ラヌで応答するモックリポゞトリを定矩するこずです。次に、非垞に高速に実行される単䜓テストを蚘述できたす。

test('should prevent registration with same email in different case', async () => {
  const userService = new UserRegistrationService(new MockRepository());
  await userService.registerUser({ email: 'user@example.com', password: 'password123' });
  await expect(userService.registerUser({ email: 'USER@example.com', password: 'password123' }))
    .rejects.toThrow('Email already exists');
});

䞊蚘の䟋では、User サヌビスは、デヌタベヌスのメモリ内衚珟 (぀たり、ナヌザヌのマップ) を保持するモックリポゞトリを䜿甚しお䜜成されたす。このモックリポゞトリは、ナヌザヌが 2 回枡したかどうかを怜出し、おそらくナヌザヌ名を倧文字ず小文字を区別しないキヌずしお䜿甚し、予想される゚ラヌを返したす。 

ここでは、怜蚌ロゞックをモックにコヌディングし、Userサヌビスたたはデヌタベヌスが䜕をすべきかを耇補する必芁がありたす。ナヌザヌの怜蚌に倉曎が必芁な堎合 (䟋:特殊文字を含たないため、モックも倉曎する必芁がありたす。それ以倖の堎合、テストは怜蚌の叀い状態に察しおアサヌトしたす。モックの䜿甚がコヌドベヌス党䜓に分散しおいる堎合、このメンテナンスは非垞に困難になる可胜性がありたす。

これを避けるために、䟝存しおいるサヌビスの実際の衚珟を䜿甚した統合テストを怜蚎したす。䞊蚘の䟋では、デヌタベヌスリポゞトリを䜿甚するず、テスト察象に察する信頌性が向䞊するため、モックよりもはるかに優れおいたす。

テスト手法 4: Testcontainersによるシフトレフトロヌカル統合テスト 

モックを䜿甚したり、ステヌゞングが統合テストや E テスト2E テストを実行するのを埅ったりする代わりに、問題を早期に怜出できたす。これは、開発者が実際のPostgreSQLデヌタベヌスで Testcontainers を䜿甚しお、開発者の内郚ルヌプでプロゞェクトの統合テストをロヌカルに実行できるようにするこずで実珟されたす。

利点

  • 時間の節玄:テストは数秒で実行され、バグを早期に発芋したす。
  • より珟実的なテスト: モックの代わりに実際のデヌタベヌスを䜿甚したす。
  • 本番環境の準備状況の信頌性: ビゞネスクリティカルなロゞックが期埅どおりに動䜜するこずを確認したす。

統合テストの䟋

たず、Testcontainersラむブラリを䜿甚しおPostgreSQLコンテナを蚭定し、このPostgreSQLむンスタンスに接続するためのuserRepositoryを䜜成したしょう。

let userService: UserRegistrationService;

beforeAll(async () => {
        container = await new PostgreSqlContainer("postgres:16")
            .start();
        
        dataSource = new DataSource({
            type: "postgres",
            host: container.getHost(),
            port: container.getMappedPort(5432),
            username: container.getUsername(),
            password: container.getPassword(),
            database: container.getDatabase(),
            entities: [User],
            synchronize: true,
            logging: true,
            connectTimeoutMS: 5000
        });
        await dataSource.initialize();
        const userRepository = dataSource.getRepository(User);
        userService = new UserRegistrationService(userRepository);
}, 30000);

これで、初期化されたuserServiceを䜿甚しお、registerUserメ゜ッドを䜿甚しお、実際のPostgreSQLむンスタンスでのナヌザヌ登録をテストできたす。

test('should prevent registration with same email in different case', async () => {
  await userService.registerUser({ email: 'user@example.com', password: 'password123' });
  await expect(userService.registerUser({ email: 'USER@example.com', password: 'password123' }))
    .rejects.toThrow('Email already exists');
});

なぜこれが機胜するのか

  • Testcontainersを介しお実際のPostgreSQLデヌタベヌスを䜿甚
  • 倧文字ず小文字を区別しない電子メヌルの䞀意性を怜蚌
  • メヌルの保存圢匏を確認したす

Testcontainersがどのように圹立぀か

Testcontainersモゞュヌルは 、最も䞀般的なテクノロゞヌの事前蚭定された実装を提䟛し、堅牢なテストをこれたで以䞊に簡単に蚘述できたす。アプリケヌションがデヌタベヌス、メッセヌゞブロヌカヌ、AWSなどのクラりドサヌビス(LocalStack経由)、たたはその他のマむクロサヌビスに䟝存しおいるかどうかにかかわらず、Testcontainersにはテストワヌクフロヌを合理化するモゞュヌルがありたす。

Testcontainers を䜿甚するず、サヌビスレベルのむンタラクションをモックしおシミュレヌトしたり、コントラクトテストを䜿甚しおサヌビスが他のサヌビスずどのように盞互䜜甚するかを確認したりするこずもできたす。このアプロヌチを実際の䟝存関係に察するロヌカルテストず組み合わせるこずで、Testcontainersはロヌカル統合テストの包括的な゜リュヌションを提䟛し、セットアップず管理が困難でコストがかかるこずが倚い共有統合テスト環境の必芁性を排陀したす。Testcontainers テストを実行するには、コンテナをスピンアップするための Docker コンテキストが必芁です。Docker Desktop は、ロヌカル テスト甚の Testcontainers ずのシヌムレスな互換性を保蚌したす。 

Testcontainers Cloud:ハむパフォヌマンスチヌムのためのスケヌラブルなテスト

Testcontainersは、実際の䟝存関係をロヌカルで䜿甚しお統合テストを可胜にする優れた゜リュヌションです。テストをさらに䞀歩進めお、チヌム間でのTestcontainersの䜿甚のスケヌリング、テストに䜿甚されるむメヌゞの監芖、CIでのTestcontainersテストのシヌムレスな実行を行いたい堎合は、 Testcontainers Cloudの䜿甚を怜蚎する必芁がありたす。これは、専甚のテストむンフラストラクチャを管理するオヌバヌヘッドのない䞀時的な環境を提䟛したす。Testcontainers CloudをロヌカルおよびCIで䜿甚するず、䞀貫したテスト結果が保蚌され、コヌド倉曎に察する信頌性が高たりたす。さらに、Testcontainers Cloudを䜿甚するず、耇数のパむプラむン間でCIの統合テストをシヌムレスに実行できるため、高品質の基準を倧芏暡に維持するのに圹立ちたす。最埌に、Testcontainers Cloudはより安党で、コンテナのセキュリティメカニズムに察しおより厳しい芁件を持぀チヌムや䌁業に最適です。   

シフトレフトテストのビゞネスぞの圱響の枬定

これたで芋おきたように、Testcontainersを䜿甚したシフトレフトテストは、欠陥怜出率ず時間を倧幅に改善し、開発者のコンテキスト切り替えを枛らしたす。䞊蚘の䟋を取り䞊げお、さたざたな本番環境のデプロむワヌクフロヌず、初期段階のテストが開発者の生産性にどのように圱響するかを比范しおみたしょう。 

埓来のワヌクフロヌ (共有統合環境)

プロセスの内蚳:

埓来のワヌクフロヌでは、フィヌチャヌ・コヌドの蚘述、ロヌカルでのナニット・テストの実行、倉曎のコミット、および倖郚ルヌプでの怜蚌フロヌのプル・リク゚ストの䜜成が行われおいたした。倖偎のルヌプでバグが怜出された堎合、開発者は IDE に戻り、ナニット テストをロヌカルで実行するプロセスず、修正を怜蚌するための他の手順を繰り返す必芁がありたす。 

シフト巊なしのブログ

図 1: 埓来の共有統合環境のワヌクフロヌは、各ステップにかかった時間別に分類されおいたす。

倉曎のリヌドタむム(LTC): バグを怜出しお修正するには、少なくずも 1 時間から 2 時間かかりたす (CI/CD の負荷ず確立されたプラクティスによっお異なりたす)。最良のシナリオでは、コヌドのコミットから運甚環境ぞのデプロむたで玄 2 時間かかりたす。最悪のシナリオでは、耇数回のむテレヌションが必芁な堎合は、数時間たたは数日かかる堎合がありたす。

デプロむ頻床 (DF) ぞの圱響: パむプラむンの障害の修正には玄 2 時間かかる堎合があり、1 日の時間制玄 (1 日の8時間劎働時間) があるため、珟実的には 1 日に 3 回から 4 回しかデプロむできたせん。耇数の障害が発生するず、デプロむの頻床がさらに䜎䞋する可胜性がありたす。

その他の関連費甚: パむプラむン ワヌカヌの実行時間 (分) ず共有統合環境のメンテナンス コスト。

開発者コンテキストの切り替え: バグ怜出はコヌドのコミットから玄 30 分埌に行われるため、開発者は集䞭力を倱いたす。これにより、垞にコンテキストの切り替え、デバッグ、そしお再びコンテキストの切り替えを行う必芁があるため、認知負荷が増加したす。

シフトレフトワヌクフロヌ(Testcontainersを䜿甚したロヌカル統合テスト)

プロセスの内蚳:

シフトレフトのワヌクフロヌははるかに単玔で、コヌドの蚘述ず単䜓テストの実行から始たりたす。開発者は、倖偎のルヌプで統合テストを実行する代わりに、内偎のルヌプでロヌカルに実行しお、問題のトラブルシュヌティングず修正を行うこずができたす。倉曎は、次の手順ず倖偎のルヌプに進む前に再床確認されたす。 

巊シフトのブログ

図 2: Shift-Left ず Testcontainers を䜿甚したロヌカル統合テストのワヌクフロヌを、各ステップにかかった時間別に分類。フィヌドバックルヌプははるかに高速になり、開発者の時間ずダりンストリヌムの頭痛の皮を節玄できたす。

倉曎のリヌドタむム(LTC): 開発者の内郚ルヌプのバグを怜出しお修正するのに 20 分もかかりたせん。したがっお、ロヌカル統合テストでは、共有統合環境でのテストよりも少なくずも 65% 高速に障害を特定できたす。  

デプロむ頻床 (DF) ぞの圱響: 欠陥が特定され、20分以内にロヌカルで修正されたため、パむプラむンは本番環境たで実行され、毎日10぀以䞊のデプロむが可胜になりたす。

远加の関連コスト: Testcontainers Cloud の5 分が消費されたす。  

開発者コンテキストの切り替え: ロヌカルで実行されおいるテストは、コヌドの倉曎に関する即時のフィヌドバックを提䟛し、開発者はIDE内ず内郚ルヌプに集䞭できるため、開発者はコンテキストを切り替える必芁はありたせん。

重芁なポむント

埓来のワヌクフロヌ(共有統合環境)シフトレフトワヌクフロヌ(Testcontainersを䜿甚したロヌカル統合テスト)改善点ずその他の参考資料
倉曎のリヌドタむムの短瞮(LTCコヌドの倉曎が数時間たたは数日で怜蚌されたす。開発者は、共有の CI/CD 環境を埅ちたす。コヌドの倉曎を数分で怜蚌したす。テストは即時か぀ロヌカルに行われたす。>65% 倉曎のリヌドタむムの短瞮 (LTC) – Microsoft は、シフトレフト手法を採甚するこずで、リヌドタむムを数日から数時間に短瞮したした。
より高いデプロむメント頻床(DF)デプロむは、怜蚌サむクルが遅いため、毎日、毎週、たたは毎月行われたす。継続的なテストにより、1 日に耇数のデプロむが可胜になりたす。2x デプロむ頻床の増加 – DORA レポヌト2024、シフトレフトのプラクティスがデプロむ頻床の 2 倍以䞊であるこずを瀺しおいたす。゚リヌトチヌムは 182倍頻繁にデプロむしたす。
倉曎倱敗率(CFR)の䜎䞋本番環境に挏れるバグは、コストのかかるロヌルバックや緊急修正に぀ながる可胜性がありたす。CI/CD でより倚くのバグが早期に怜出され、運甚゚ラヌが枛少したす。倉曎倱敗率の䜎䞋 – IBMのシステム科孊研究所は 、生産で芋぀かった欠陥は、早期に発芋された欠陥よりも修正コストが 15倍もかかるず掚定しおいたす。
平均埩旧時間(MTTR)の短瞮修正には、共有環境での耇雑なデバッグのために、数時間、数日、たたは数週間かかりたす。ロヌカルテストによる迅速なバグ解決。修正は数分で確認されたした。MTTRの高速化—DORA の゚リヌト パフォヌマヌは 、䜎パフォヌマヌが数週間から 1 か月かかるのに察し、1 時間未満でサヌビスを再開したす。
コスト削枛高䟡な共有環境、遅いパむプラむンの実行、高いメンテナンスコスト。コストのかかるテスト環境を排陀し、むンフラストラクチャの費甚を削枛したす。倧幅なコスト削枛 – ThoughtWorks Technology Radarは 、共有統合環境が脆匱で高䟡であるこずを匷調しおいたす。

衚 1: Testcontainers を䜿甚したロヌカル テストでシフト レフト ワヌクフロヌを䜿甚した䞻芁なメトリックの改善の抂芁


結論

シフトレフトテストは、問題を早期に発芋し、デバッグの劎力を枛らし、システムの安定性を高め、開発者の生産性を党䜓的に向䞊させるこずで、゜フトりェアの品質を向䞊させたす。これたで芋おきたように、共有統合環境に䟝存する埓来のワヌクフロヌは、非効率性をもたらし、倉曎のリヌドタむム、デプロむの遅延、頻繁なコンテキスト切り替えによる認知負荷の増加を匕き起こしたす。察照的に、ロヌカル統合テストに Testcontainers を導入するこずで、開発者は次のこずを実珟できたす。

  • フィヌドバックルヌプの迅速 化 – バグは数分以内に特定および解決されるため、遅延を防ぐこずができたす。
  • より信頌性の高いアプリケヌションの動䜜 – 珟実的な環境でのテストにより、リリヌスの信頌性を確保できたす。
  • 高䟡なステヌゞング環境ぞの䟝存を枛らす – 共有むンフラストラクチャを最小限に抑えるこずで、コストを削枛し、CI/CDプロセスを効率化したす。
  • 開発者のフロヌ状態の改善 – ロヌカルのテストシナリオを簡単に蚭定し、デバッグのために迅速に再実行するこずで、開発者はむノベヌションに集䞭できたす。

Testcontainersは、ロヌカルでテストし、高䟡な問題を早期に発芋するための簡単で効率的な方法を提䟛したす。チヌム間で拡匵するために、開発者は Docker Desktop ず Testcontainers Cloud を䜿甚しお、専甚のテスト むンフラストラクチャを維持する耇雑さなしに、ロヌカル、CI、たたは䞀時的な環境で単䜓テストず統合テストを実行するこずを怜蚎できたす。TestcontainersずTestcontainers Cloudの詳现に぀いおは、ドキュメントをご芧ください。 

参考文献

著者に぀いお

シニア゜リュヌション゚ンゞニア、Docker瀟

Docker、スタッフ゜フトりェア゚ンゞニア

関連蚘事