マイクロサービスのQA・セキュリティ自動化テスト社内ツール「Testdeck」をOSS化しました!

こんにちは。Product Securityチームの@gloriaです。前回、自動化テストエンジニアからセキュリティエンジニアへのキャリアチェンジについて記事を書きました。

今日は、最近OSSとして公開した社内ツールのプロジェクトについてお話をしたいと思います!

「Testdeck」とは?

TestdeckはGolangで書いたgRPCマイクロサービスのインテグレーションテスト、エンドツーエンドテスト(E2E)とセキュリティテストの自動化ツールです。以下の機能を提供しています:

  • gRPCとHTTPエンドポイントのインテグレーションテスト・E2Eテスト ファズテスト
  • 悪意のあるペイロードの注入(Burp SuiteのIntruderという機能のように)
  • gRPCとHTTPリクエストのユーティリティメソッド
  • CharlesやBurp Suiteなどのデバッギングプロクシーに接続し、リクエストのインタセプト、分析、変更、リプレイなど

こちらの記事の説明通り、メルカリのマイクロサービスはKubernetesクラウド環境にデプロイされています。Testdeckの導入の前に、マイクロサービスのテストはモックを使っていて、サービスとシステムの他の部分の通信を実際に確認していなかったので、実際のインテグレーションテスト・E2Eテストとは異なりました。

TestdeckのコンセプトはKubernetesクラスター内に一時的なテストサービスをデプロイして、サービスのエンドポイントを直接叩き、レスポンスを確認することです。要するに、テストサービスは実際に利用するサービスと同じようにサービスと通信するわけです。テストサービスはKubernetesジョブとしてデプロイされるので、テストの実行が終わったらポッドが自動的に終了します。

Testdeckのテストサービスは実際のコンシューマサービスのようにサービスと通信します。

Testdeckのテストケースは4つのステージに分けています(全てのステージはオプショナルで、必要なステージだけを使っても良いです)。このデザインの理由を記事の後半で詳しく説明します。

4ステージのデザイン

簡単な例として、以下のようにテストケースが書けます。TestdeckはGolangの提供しているテストライブラリに基づいて作成されたので、ユニットテストと同じように書いて、実行できます!

テストケースの例。go testなどのユニットテストのコマンドも使えます。

そして、Testdeckのアーキテクチャーは以下のようになります:

  1. マイクロサービスはSpinnakerでKubernetesポッドにデプロイする
  2. マイクロサービスのテストは同様にSpinnakerで別のポッドにデプロイして、テストをKubernetesジョブとして実行する
  3. テスト結果はデータベースに保存する
  4. 開発チームにPassかFailとテストレポートのURLを含むSlack通知を送る
  5. 開発チームはURLにアクセスし、ダッシュボードでテスト結果を確認する(ダッシュボードはデータベースで保存されたテスト結果を表示する)

Testdeckのメリットとは?

以下はTestdeckと類似するテストフレームワークと比較した時のメリットです:

1)デバッグ作業が楽

Testdeckのテストケースはテストが失敗したら、おおよそどこで不具合があったのかを把握するために4つのステージに分けています。E2Eテストは大体長く、テストデータの作成やテストアカウントの準備などのセットアップが多いので、テストケースを分けて一見でどこで失敗したのかを見えるようにしたらデバッギングが楽になるのではないかと思い、「4ステージ」のデザインにしました:

  • ArrangeかAfterのステージで失敗したら、テストが依存していること(テストアカウントやテストデーターなど)は問題がある可能性が高いと思われます
  • Actで失敗したら、マイクロサービス自体は問題がある可能性が高いと思われます(エンドポイントはエラーを返したり、通信ができなかったりする場合など)
  • Assertで失敗したら、返したレスポンスと予想したのは異なっています。必ずバグがある理由で落ちたとは言えなく、レスポンスの内容やスペックが変わった理由で落ちる場合もあるので、調査が必要だと思われます

2)メトリクスの収集

テスト結果のメトリクス(失敗したテスト数、失敗した理由、テスト実行時間、など)をきちんと収集するのは自動化テストのベストプラクティスです。メトリクスの分析でフレーキーテスト(ランダムに失敗していて信頼性のないテストケース)など、様々な課題が明確になることで、テストを改善することが出来ます。

Testdeckはレポーティングを分析するために、指定されたデータベースにテスト結果を保存する機能を提供しています。メトリクスを収集したい場合は、以下の設定をすれば可能になります:

  1. DB_URLという環境数にデータベースにアクセスするAPIのroot URLを設定する
  2. Testdeckをcloneして、db.goをデータベースのスキーマに合わせて書き直す(簡単な例として私たちの設定を共有しましたが、必要なメトリクスは異なる場合もあるので、変更しても良いです)

データベースにメトリクスを保存する場合に、社内のステークホルダー(QA、PM、など)もテスト結果が見えるようにダッシュボードで可視化するのもベストプラクティスの一つです。以下は私たちが作った簡単なレポーティングダッシュボードで、テスト結果(どのステージで失敗したのかとアウトプットログも含め)が社内の誰もが見えるようにしています。

3)エンジニア達の使い慣れたテクノロジースタック

エンジニア達の愛用しているテクノロジースタックと一致するために、TestdeckをGolangで開発し、Golangのテストライブラリに基づいて、デプロイメントツールもSpinnakerにしました。その理由は、「シフトレフトテスティング」を促進したいからです。従来の方法では、ソフトウェア開発ライフサイクル(SDLC)のテスト段階でテスティングが始まりますが、近年、実装段階でテスティングを開始し、エンジニア達は自分の実施したコードのクオリティの責任を持ち、自分で自動化テストを書くパターンはもう珍しくありません。これはいわゆる「シフトレフトテスティング」という考え方です。エンジニア達の使い慣れたテクノロジースタックを選ぶことで、不自由な技術を身に付ける学習時間を減少出来るはずなので、スムーズにシフトレフトテスティングが出来るのではないかと思いました。

「シフトレフトテスティング」は近年、Facebookやグーグルなどの大手企業でも導入されています。

4)機能拡張または他のGolangライブラリとのインテグレーションも可能です

Testdeckは完全にGolangで書いてあるので、google/gofuzz(ファズテストでランダムな入力を作成するライブラリ)やstretchr/testify(ユニットテストでよく使うアサーションのライブラリ)などのGolangライブラリをインテグレートするのは簡単に出来ます。また、手軽に新しいフィーチャーを追加するのも可能なので、機能拡張しやすくて、チームのニーズに合わせられるとてもカスタマイズ可能なツールになります。

5)QAとセキュリティのテストに一つのツール

私のキャリアチェンジで気付いたのは、QAとセキュリティの分野は意外に共通点が多いことです。2つの例を挙げれば、(1)近年QAとセキュリティもどんどん自動化に頼って来ました(いわゆる「シフトレフトテスティング」と「シフトレフトセキュリティ」)、(2)SDLCのデザインフェーズと実装フェーズでクオリティとセキュリティの考えを含めなければ、質が良くてセキュアなソフトウェアを作ることはできません。また、QAとセキュリティのテストは意外と似ていて、自然に重複した部分があります。QAは一般的なユーザーか少し奇妙なユーザーの視点からテストを考えますが、セキュリティは悪意のあるユーザーとしてテストを行います。そして、入力検証、エラーケース、ビジネスロジック(得に認証認可周りの機能)などのテストケースはQAとセキュリティ両方のテストでも行われるので、一つのツールで出来れば便利ではないかと思いました。そうすると、複数のツールをマスターする学習時間を減らすこともでき、ベースラインのクオリティとセキュリティを満たすために毎回コードコミットでQAとセキュリティのテストを一緒に実行することも出来ます。

QAとセキュリティテストのユーザー視点。星印が付いている項目は自然に重複しているテストです。

Testdeckのセットアップ

Testdeckのセットアップが気になる方、是非ドキュメンテーションをご覧ください。

更に、TestdeckのテストケースはKubernetesクラウド環境で実行されるので、手元で開発する時にTelepresenceを使うのはお勧めです。そうすると、手元でテストを実行する時でもクラスター内のマイクロサービスに直接にアクセスができ、テストの実装・デバッグがしやすくなります。

終わりに

メルカリバックエンドのマイクロサービス化はどんどん拡大してきており、今の時点では百サービス以上が存在しているため、手動でQAとセキュリティのテストを行うのはもうスケーラブルではありません。私たちの開発チームは少しずつDevOpsのカルチャーに近づいていて、エンジニア達はSDLC全ての段階で責任を持つようになりました。そして、我々はエンジニアにとって使いやすくて、簡単に新しい機能や、他のGolangライブラリを追加するのが可能かつQAとセキュリティテスティングの両方を実行できる一つのツールを作ることを目指してきました。

QAとセキュリティテストを自動化する方法について少しでもインスピレーションになれればと思っています。Testdeckについてもっと詳しく知りたい方はいらっしゃったら、是非公開したリポジトリをご覧ください。