コドモン Product Team Blog

株式会社コドモンの開発チームで運営しているブログです。エンジニアやPdMメンバーが、プロダクトや技術やチームについて発信します!

コドモンにおける決済基盤のテストの紹介

こんにちは。QAエンジニアの砂川です。

こちらの記事は、コドモンAdvent Calendar 16日目 および ソフトウェアテスト Advent Calendar 2024 19日目の記事です。

本日は、コドモンの決済機能のテストを行うにあたり、どのようなテスト戦略で品質保証をしてきたのかを紹介します。

決済基盤の紹介

コドモンのさまざまな機能のうち、用品販売やいつでも請求*1のように、施設の集金業務を支援する機能があります。

決済基盤は、集金業務を支援するそれらのサービスからクレジットカードやコンビニ決済のリクエストを受けつけ、決済代行業者に連携するサービスとして稼働しています。

決済機能のシステム相関図

決済基盤のテストに関して

決済基盤が実際のユーザーからのリクエストを受けつけるまでに、様々なシステムが結合をしています。

用品販売を例にすると、

・WEBクライアント、保護者アプリ + 用品販売
・用品販売 + 決済基盤
・決済基盤 + 決済代行業者

という単純なサービスごとの結合の品質保証のほかに、

・WEBクライアント、保護者アプリ+ 用品販売 + 決済基盤 + 決済代行業者

のように実際の運用に即したサービス間の結合における品質保証をする必要がありました。

これらに関しては、私たちは下記のようなテスト戦略を取るようにしました。


1. 機能テストは、Unit Test・Integration Test・System Test と分けて、テストレベルが上がるごとに結合部分を増やしていく
 例えば、Unit Test ではBackendの関数やクラス単位でのテスト、Integration Test では In / Out を意識した機能検証というように、テストの目的も定めてエンジニアと共有しました
 下図がテストのスコープのイメージとなります


2. Integration Test において、プロセス間の結合より外の世界がある場合は、モックを利用した自動テストを行い、挙動の確認を常にし続ける

3. 決済基盤 + 決済代行業者のIntegration Test においては、モックでの結合試験だけでなく、別途決済代行業者のテスト環境と接続した状態での結合試験も自動テストで動くようにしておく

4. System Test は、自動テストでハッピーパスも行うのに加えて、マニュアルテストも実施する。必要に応じて、障害テストや高負荷テスト、セキュリティテストも実施する

5. ステージング環境等での結合試験が終わった後、本番環境でも実際の決済ができるかをチェックする

特に、私たちが重視したのは、APIの Integration Test 部分です。

次の章では、Integration Test に力を入れる理由を紹介します。

決済基盤におけるIntegration Test の位置付け

なぜIntegration Test に力を入れているのかというと、下記の点を防ぎたいと考えているためです。

・マイクロサービスという特性上、結合部分の齟齬が本番障害に直結しやすい状況となっている
・決済という金銭を扱うプロダクトであるため、本番障害が起きた時の損害が大きい
・決済代行業者というコドモンだけでは、ハンドリングができないサービスがシステムの外側にいるため、そこのサービスの影響によるデグレード

このように不具合がユーザーにデメリットを及ぼすプロダクトである以上、決済基盤におけるInput と Output の結果が常に開発者が想定している状態か確認する必要があります。

そうした時に、API層のIntegration Test を準備して自動テストとして回しておけば、処理の正しさを担保し続けることができると考えました。

特にコドモンでは、テストをgaugeというツールを使って作っているので、APIの仕様書としての挙動も残しておけるという点で、さまざまなサービスから利用される決済基盤においては、相性がいいと考えました。*2*3

決済基盤のIntegration Test の構成に関して

決済基盤のIntegration Test では、主に下記の2点の結合部分に注力をしています。

・用品販売 + 決済基盤
・決済基盤 + 決済代行業者

では、それぞれどのような構成でテストを行っているか紹介します。

用品販売 + 決済基盤

決済基盤単体のIntegration Test(自動テスト)

このテストでは、決済基盤が公開しているAPIに対してリクエストを飛ばし、決済基盤がどのようなリクエストを決済代行業者に送り、決済基盤のクライアント(用品販売やいつでも請求)に対してどのようなレスポンスを返すかを考慮して、Integration Test を考えます。

実際に、決済基盤が受けるリクエストのパターンとしても、下記のようなパターンが考えられます。

・決済手段
 ・クレジットカード
  ・カードブランド
  ・支払方法
 ・コンビニ決済
・金額
・施設ID(クレジットカード決済の利用には審査が必要なため)
 etc...

これらのうち、正常系のパラメータのパターンやタイミング、順序を考慮した準正常系が本当に機能担保できているかということはIntegration Test で実施しています。

アサートする対象としては、下記を対象に期待値を記載するようにしています。

・HTTP Status Code
・Response Body の値
・決済基盤DB のカラム値
・(準正常系の場合) Error Code

つまり、図にすると、下記のような図になります。(赤字のところがアサートするところ)

用品販売+決済基盤のIntegration Test の概略図

このように、決済基盤が公開しているAPIの仕様をテストで守っています。

用品販売 + 決済基盤の結合部分のIntegration Test

用品販売と決済基盤は同じチームで開発・保守をしているので、開発者がお互いのシステムの仕様を知り尽くしている状況です。

そのため、用品販売API単体のIntegration Test でも、決済基盤をモックとして準備して、In / Out を意識した機能検証を自動テストで回しています。

新規機能のリリース直前となった時は、用品販売と決済基盤をともにデプロイして、結合させた状態をマニュアルテストで確認しています。

実際にサーバー間を結合させた自動テストがないのは課題として感じており、今後の課題としてチームで品質保証の戦略をより良くしていこうと考えている部分にもなります。

決済基盤 + 決済代行業者

決済基盤の先には、決済代行業者がいます。

決済代行業者は社外のシステムを利用するため、私たちではコントロールできず、急な仕様変更や想定しない挙動が発生することも考えられます。

そこで、用品販売 + 決済基盤の結合部分では、モックとしていた決済代行業者も本物(決済代行業者が準備するテスト環境)と接続したテストを準備しておく必要があると考えました。

観点としては、下記の観点に絞って守っています。

・決済データが作られてからの状態遷移の確認
 ・決済データがつくられてからの状態遷移が1スイッチカバレッジ 100 %になるように作成*4
・上記テスト完了後の決済データの状態が決済基盤API内で正しく利用されることを確認
 ・売上確定となった決済データが、売上データとして計算されていること
 ・オーソリ状態のままだったり、キャンセルされたデータは、その後売上データとして計算されないこと

なぜ、この観点に絞ったかというと、決済基盤のCUJ(クリティカルユーザージャーニー)となるフローが決済代行業者の変更によって守れなくなることはないかということを検知したいと考えたためです。

もちろん、エラーが返ってきた時のエラーハンドリングが正しいかどうかをチェックする必要もあると思いますが、決済ネットワークにおいて様々なエラーがある中で、

その仕様までを決済基盤が全て吸収して、網羅的にテストを作るのはコストに見合わないと考えています。

もし、上記のようなエラーがあった場合は、一旦は開発側での対応とすることをチームの方針として、そのエラーを吸収する仕組みを作るかどうかも、チームで判断するようにしています。

つまり、決済基盤 + 決済代行業者の結合部分のアサートの関係を下記のようになります。

決済基盤+決済代行業者のIntegration Test の概略図

このように決済代行業者との整合性担保も守っています。

クライアント+ 用品販売 + 決済基盤 + 決済代行業者

このように、マイクロサービス同士や外部連携先との結合試験も行って、機能担保はある程度守れている状況を作っていますが、やはりユーザーに影響がないとは言い切れない状況です。

そのため、全てをつなげた結合試験(チームではワークフローテストやマニュアルテストと名付けています)も実施しています。

ワークフローテスト

このテストを作っているのは、開発に関係しているQAエンジニアやエンジニアではなく、プロダクトマネージャー(PdM)やプロダクトデザイナー(PD)とQAエンジニアで作っています。

確認する観点としては、下記の観点を対象にし、PdM、PD、QAエンジニアでgaugeのテストを作っています。

・業務要件として必要な要件が満たせているか確認する
・クリティカルな不具合がないかどうか(例:請求金額や請求先の不備 など)
・他社との強みとなる機能が正常に動作しているか確認する

このテストは、すべてが本番相当の機能を満たしているということがテスト環境の要件となるので、コドモンではステージング環境で実施するようにしています。

マニュアルテスト

このテストは、いわゆるマニュアルでやる機能テストのことを指します。

特に、ユーザーから見た「支払い」ができないというのは、決済基盤のクリティカルなバグとなるので、かなり込み入った観点のテストなどは、システムテストを実施します。

もちろん、ローンチ直前となった時には、少額決済を本番環境でやるということもテストケースとすることもして、最終的な機能確認を実施しています。

まとめ

ここまで決済基盤を守るテストの考え方の紹介をさせていただきました。

決済基盤は、コドモンの集金系の機能を支える根幹となるので、より品質を求められる状態です。

現在は、用品販売やいつでも請求と決済基盤を同じチームが開発を進めているため、上記のようなテストで守れていたと感じてますが、今後事業拡大をしていく中で決済基盤のあり方が変わってくると考えています。

そうした時に、より決済基盤があるべき責務を果たすために、上記からもう一歩踏み込んだテスト戦略を考えていく必要があるとも感じてます。(例:本格的にサーバー間の結合をするとなった時の結合試験としてどのような戦略を取るか など)

また、機能テストに絞った話をさせていただきましたが、機会があれば非機能試験や信頼性テスト(障害試験)の様子も紹介させていただければと考えています。

最後に

コドモンでは、QAエンジニアを絶賛大募集中です!

保育ドメインはわからない方でも、決済や小売、勘定系のシステムもありますので、興味がある方は是非カジュアル面談にお越しください!

herp.careers

*1:施設が月極以外のタイミングで請求し、集金する機能

*2:gaugeを使ったテストの紹介は、こちらの資料をご覧ください

*3:実行環境の記事もありますので、こちらもよかったら読んでみてください

*4:状態遷移テストの詳細は、[こちら](https://www.aiqveone.co.jp/blog/state-transition-test/)の記事を参照ください