はじめまして。メルペイのQA Engineer(以降QAE)チームのtakamaです。
本記事では、QAチーム内で発生した技術的負債にどう立ち向かい、どのような結果が得られたかについて紹介します。
「QAチームって開発するの? 」「QAの技術的負債って何なの?」と思われるかもしれません。今回紹介するケースはテストコードの書き方で発生した負債を指します。
テストコードでよく言われる困るケースとしては以下の2点だと思います。
- ひとまず自動化は成し遂げられたが、メンテナンスコストが高くて活用できない
- テストコードを書いてみたが、繰り返し使えない
いずれも自動化が目的になると、陥りがちなパターンかなと考えます。
今回紹介するケースは上述のひとつめのパターンで、一度自動化したがメンテナンスコストが高く、運用時に疲弊してしまった経験から、使用するツールから見直し、自動化の仕組みを根底から作り直したという内容となります。その結果、自動化前は1日に0.5ケース実行していたのが、自動化後は1日5ケース実行できるようになりました。
前置き
- 私の担当していたマイクロサービスは、メルカリやCIC(指定信用情報機関)から信用情報を収集し、お客さま各個人に対しての与信枠を算出するようなサービスです。解説した記事があります。こちらも読んでみてください。
- お客様が「定額払い」を利用している場合、毎月CICへお客様の利用状況を登録する必要(信用情報の登録)があり、これも担当していたマイクロサービスで行っています
- 今回紹介するのは登録の前準備である、お客様の利用状況をデータ化する機能の話となっています
- 便宜上、
利用データ作成機能
とします
利用データ作成機能のQA方法
自動化の経緯等を話す前に、本機能における初期のQA方法を紹介します。
手順としては以下の通りです。
- 検証に利用するテストデータ作成(API実行)
- メルペイスマート払い(翌月払い/定額払い)のさまざまな使われ方を想定した、メルカリ/メルペイの操作(API実行)
- 利用データ作成機能の実行(SpreadSheetでコマンド作成→ジョブ実行)
- マイクロサービスで管理しているデータベース(Spanner)の値を確認
APIの実行には、Postmanを利用し、ジョブの実行はkubectlのコマンド
を用いて、terminal上で実行していました。
QA方法の課題と自動化の経緯
QA方法における課題の概要は以下の通りです。
- 担当したマイクロサービス(以降マイクロサービスA)の管轄外となる機能の操作履歴を作成することから、担当外のマイクロサービス(以降マイクロサービスB)の機能についても制限やドメイン理解が必要だった
(仕様理解の幅が広い)
- APIの実行とジョブの実行を順々に手動実行するためミスが多かった
(実行コスト高)
- Postmanのcollection(テストコード)は、実行の時間間隔が空くとメンテがほぼ必須となる構成だった
(メンテナンスコスト高)
- Postmanのcollectionをテンプレートとなるcollectionをベースに実行者が編集していたが、編集難易度が高かった
(追加・メンテナンスコスト高)
- APIのリクエスト方法に仕様変更が入ると、テンプレートおよびテンプレートを用いたcollectionすべてを修正する必要があった
(メンテナンスコスト高)
ここでのメンテナンスコスト高
という点が、技術的負債に繋がるポイントとなっています。
上述の課題を解決しようと試みたのですが、一筋縄には行かず、段階的に解決できることから着手しました。
以降に取り組み内容を時系列で紹介していきます。
定額払いリリース時
試したこと
いきなり自動化を目指すのは難しいので、最初はマニュアルテスト
で様子見することにしました。
実行時フロー
残った課題
- このフェーズでは、マイクロサービスBを理解してないとAPIがそもそも正常に実行できない
実行難易度の高さ
と、難易度と相まって実行時のミスが多く、実行コストの高さ
が強い課題として残りました - 実際、
1日に0.5ケース(1ケースに大体2日くらい)
のスピード感で、それが実行時の人為的なミスによりさらに時間がかかりました
定額払い手数料導入 対応フェーズ
試したこと
このフェーズでは、定額払いリリース時に残った課題として、実行難易度とコストの高さを軽減するために、PostmanのRunnerの機能を用いて、以下のような形でユーザ作成
、メルカリ/メルペイの操作
を対象に自動化を図ることにしました。
- Postmanで、各シナリオのテンプレートとなる汎用的なcollectionファイルを作成
- 月ごとにテンプレートを編集し、順次実行可能なシナリオを作成
- ユーザ作成は月ごとのシナリオに含むようにした
- 作成したシナリオをPostmanのRunnerの機能で実行
実行時フロー
効果
- 実行者がcollectionのパズルでシナリオを組めるようになり、実行難易度が下がった
- 再実行のスピードが早くなった
残った課題
- エラーが発生した時に、結局詳しい人に聞かなくてはならない状況で、実行者の依存度が変わらなかった
- ジョブ実行以降(特にテーブル確認箇所)が効率的でなく、まだ確認ミスが残ってしまっていた
- 実行スピードが少し早くなったとはいえ、1ケースを実行するのに、大体1日くらいかかってしまう
運用フェーズ
試したこと
このフェーズでは、前フェーズで残った課題である、スプレッドシートの操作が必要でちょっと手間のいるジョブ実行
、目視確認でどうしても確認ミスが発生してしまっていたテーブルデータの確認
を対象に、以下のような形で自動化を図ることにしました。
- 以下のようにコマンドの生成、実行に必要なパラメータをオプション指定することで、ジョブを実行できるスクリプトの作成(スプレッドシートの操作の排除)
sh new_script.sh -環境番号 20 -契約番号 xxx -実行年月 202112
※コマンドのイメージです
- 利用データ作成機能の対象となるテーブルデータを確認できるように、内製ツールを拡張
実行時フロー
効果
-
ジョブ実行時が1コマンドで実行できるようになりました。フローを部分的に記すと以下の通りです
- 対応前
- 対応後
- 対応前
-
テーブルデータの確認も、はじめに期待値をYAMLで定義する手間が増えましたが、2回目以降は拡張した内製ツールにより機械的に確認できます
残った課題
- ジョブ実行以降は機械的にできるようになりましたが、全体でみると、
API実行→ジョブ実行→API実行→ジョブ実行→...→テーブルデータの確認
となっており、ジョブをAPI実行の合間(月単位)に都度実行しなくてはならないため、まだまだ実行コストの面で課題が残りました
自動化を本気で考えるフェーズ
ここまで色々試してきましたが、最初にあげた課題を振り返ると、メンテナンスコストの面が実はあまり解決できていませんでした。
またインシデント対応が発生した際、インシデントに対する修正確認をするだけではなく、修正誤りや修正漏れによる二次被害も絶対に発生させてはいけません。確認を慎重にするということもあり、QAには数週間を要すこともあり、お客さまに影響が出る出ないのギリギリのラインを綱渡りをしていました。
そんな中、色々と限界が来てしまい、運用中のとあるタイミングで本気でメンテナンスコスト面も解決する形での自動化を実現することを決意しました。
課題の再掲
既に紹介しましたが、QA実行時の課題は以下のようなものでした。
- 担当したマイクロサービスAの管轄外となる機能の操作履歴を作成することから、マイクロサービスBの機能についても制限やドメイン理解が必要だった
(仕様理解の幅が広い)
- APIの実行とジョブの実行を順々に手動実行するためミスが多かった
(実行コスト高)
- Postmanのcollection(テストコード)は、実行の時間間隔が空くとメンテがほぼ必須となる構成だった
(メンテナンスコスト高)
- Postmanのcollectionをテンプレートとなるcollectionをベースに実行者が編集していたが、編集難易度が高かった
(追加・メンテナンスコスト高)
- APIのリクエスト方法に仕様変更が入ると、テンプレートおよびテンプレートを用いたcollectionすべてを修正する必要があった
(メンテナンスコスト高)
課題に対して考えたこと
課題の1と2については、マイクロサービスBにおいて把握すべきデータベーステーブルが17個あり、それぞれのデータがどのように入ってくるのかを理解してAPIを実行しないといけない点が、実行ハードルを上げている要因となります。
また、デバッグ機能である環境の時間変更が完全に有効になっておらず、とあるテーブルのとある時間フィールドだけ現在時刻で更新され、期待値にならないという問題も相まって、とても苦労しました。ただ、これらの課題に対しては、マイクロサービスBのQAチームに依存する形でAPIが実行できれば問題ない
と考えました。
具体的には、API実行部分をマイクロサービスBの担当QAチームのテストシナリオを流用することで、自担当以外のマイクロサービスのドメイン知識を求められることに対し、実行者は中身を意識する必要がなくなると考えました。
もしマイクロサービスBの流用したシナリオが動かなくなっているのであれば、それはマイクロサービスBのQAチーム側も困ることだし、仕様を把握しているチームで直した方が全体的な効率が良いという考えです。
しかしこの形を取るのは、この時点でのPostmanの運用方法では難しかったです。
やり方を工夫すれば、このままPostmanを有効活用できるかもしれませんでしたが、他のテストシナリオを参照できる他のOSSテストツールscenarigoに置き換えることにしました。このテストツールはテストシナリオをYAML形式で記述できるAPI検証ツールです。これはメルペイのArchitectチームが作成、メンテナンスしてくれているOSSで、いつか利用データ作成機能でも使いたいと思っていました。
scenarigoを用いるという前提で考えた際、他にも副作用がありました。それは、プラグインを実装することでジョブをシナリオの中で実行できるという内容です。ジョブがシナリオ上で実行できることで、課題として残っていた、API実行→ジョブ実行→API実行→ジョブ実行→...
と繰り返す部分が一つのシナリオでまとめることができ、1コマンドで利用データの作成部分が完結できそうという魅力もありました。
以上のことから、Postmanで半自動化した仕組みを捨て、
大きく2ステップで新たな自動化の仕組みを実装することを決意しました。
- scenarigoで、メルカリ/メルペイの利用データを作成
- 内製ツールで、作成データと期待値のチェック
2は既に完成しているため、1のPostmanからscenarigoへのテストコードのリプレイス作業が主な作業となりました。
cf. scenarigo:【書き起こし】Scenario-Based Integration Testing Platform for Microservices – 森 健太【Merpay Tech Fest 2021】
自動化を成し遂げるためにしたこと
とはいえ、新たな自動化を達成するためにも課題が存在しました。
自動化をする決意をした時点での課題は以下の通りです。
- マイクロサービスBのQAチームが作成したシナリオは、汎用的に使えるシナリオ(以降共通シナリオ)が整備されていなかった(そのまま参照できる状況ではなかった)
- 自チームと、 マイクロサービスBのQAチームとでは、ツールの活用方法が異なっていた
上述の課題を解決するためには、マイクロサービスBのQAチームとの連携は必要で、とても重要なことでした。理由としては、共通シナリオという形でテストケースをマイクロサービス間で共有するためです。
その前提で、以下のようなステップでアクションを取れば解決できると考え、行動に移しました。
- 以下のようなお客さまのアクション単位での共通シナリオを作成する
- 一括払いができるユーザを作成
- XX円のネット決済を実行
- NN円で定額払い設定 等
- 1で作成した共通シナリオをベースに、シンプルなシナリオを数シナリオ作成する
- 2で発覚した問題がクリティカルなものがあれば中断の判断をする(結果的に問題なかった)
- 1で作成した共通シナリオをベースに、リグレッションテストで必要なシナリオを全て作成する(自チームとしてのゴールはココ)
- 依存先チームも1で作成した共通シナリオをベースに、既存シナリオをリファクタリングしていく(マイクロサービスBのQAチームとしてのゴールはココ)
結果、まだ課題は残りつつも、やりたかった自動化は達成できました!
実行も、1日で0.5ケースだったのが、1日で5ケースほど確認できるスピード感になりました!
- 1st release時
- 自動化後
残る課題
- テスト環境の仕組みの問題で、一部データパッチが必要になっている状況
- こちらの課題に対してはまずノウハウ集を作成し、こういう時に、こうなってた場合、こうパッチを当てるといった手順を明確にした
- 将来的にはテスト環境の仕組みを修正するため、修正のタイミングで課題がクリアになる予定
- リグレッションテストでツールを2つ使用するため、ちょっと面倒
- こちらの課題は、テーブルのデータをDebugAPIで取得できれば、1ツール(scenarigo)で閉じられるので、開発チームの余裕がでたタイミングで相談したい思いです
- 必要なDebugAPIを、QAEでも実装できるようになるとかもやってみたい思いはあります
今回のことで感じたこと
- マイクロサービスに対するシナリオテストの運用では、マイクロサービスの境界がボトルネックでした。それは境界付近はテストに必要なドメイン知識の幅が広くなるポイントだからです。この境界を、共通のシナリオテストという仕組みを作ったことでテストの工数が格段に圧縮できました
- 共通のシナリオテストの運用は関連マイクロサービス間で合意しておく必要がありますが、求められるドメイン知識が狭くなるので費用対効果は素晴らしいものがありました!
なので、できるだけ早い段階で、マイクロサービス間と協力してQA活動できるよう(できれば仕組み的に)、最初からAll for Oneに巻き込んだ方が絶対に良いと強く思いました - 全自動が難しくても、一部自動化することで、一旦楽できる!
- こちらでも段階的な自動化について話させていただいてます!
最後に
- 本記事では、とりあえず半自動化してみたものの、それが技術負債となり、最終的にはツールを変えるレベルで自動化基盤を整えてみたという内容を紹介させていただきました。
時にはGo Boldにやり方を変えてみるのも最終的にはプラスになるケースがあるということと、そこに至るまでの苦労が伝われば幸いです
(ただ、今回はscnarigoにリプレイスしましたが、APIを単体で実行して確認したいケースなどPostmanを用いるケースはまだまだ多いので、ツールの使い分けは見極めるべきと考えます) - 本記事でmerpayのQA Engineerに興味を少しでも持っていただけたら幸いです。
現在merpayのミッション・バリューに共感できるQA Engineerを募集しております。興味を持っていただき、一緒に働き、切磋琢磨できる仲間をお待ちしております!
また、2月16日にメルペイ主催のイベント「QA Talk〜QA積極募集企業紹介 & IT企業4社のパネルディスカッション〜」を開催予定です。
最後までお読みいただきありがとうございました。