ウチのQAの現在地

unionsep

Postman

198 Words

2024-12-15 19:00 -0800


これは Kyash Advent Calendar 2024 の16日目の記事です。

取るに足らないことですが、この記事のタイトルを思いついたとき、一丁目一番地というキーワードを連想しました。 私もそれなりに歳を重ね、それなりに物事を見通せる人になってきた気がしますが、「押っ取り刀」という聞いたこともない素晴らしい語感と意味を持つ言葉を教えてもらった先輩を思い出して、まだまだ知らないことがあるんだな〜と感慨に耽っています。年取ったもんだなぁ〜 前回 もAdvent Calendarを公開したのですが、もう1年経つんですね。 Kyash に入社して丸2年経過しました。

去年に引き続き、Backend Engineerとしてサーバー開発を続けていました。成功したり失敗したりしましたが、近頃、組織変更があって、QA(品質保証)の人に戻ることになりました。 会社にとってとても重要で、時間をかけて育てていきたい機能がリリースされるにあたり、失敗をできる限り低減したいという考えから、独立したQAが欲しいとのことで、私にお声がかかったようです。 1年ほど、プロダクトの開発にどっぷり浸かっていたので、色々見通せる部分が広くなってきたこと、これはなかなかに動かすのはしんどそうだなぁと思う部分が見えてきたタイミングでした。 チームに入ってから、少しの間、静観しながらメンバーの雰囲気を窺っていたのですが、私なりに課題に思えるテーマが見えてきました。

API Firstな感じがあまりしない

KyashのBackend Engineerのサーバー開発は、ほとんどがWeb API開発になります。 既存のAPI Endpointを利用するか、新しいEndpointを生やすのか、アクセスが重複したときの排他制御はどのように設計するのか、受け取ったレスポンスをどのようにハンドリングするのか、みたいな設計にまつわる議論がほとんどです。 API開発が盛んなので、機能を実装する前にもう少しAPI仕様を作り込んで、先にテストを書いてから開発に着手したほうが良いのではと感じていました。

「動いて風を知る」という標語をValueに掲げるKyashの文化は、開発前に仕様をかっちり固めてしまう前に実装に入り、不都合があればメンバー同士で話し合って軌道を修正していくスタイルが多いです。例えば、まずは動くものを短期間で開発し、それをレビューしながら改善を重ねるアプローチを重視しています。 今まではうまく機能していましたが、私が入ったチームが開発する機能は他社のチームとガッチリ協業する必要があり、うまく機能していないようでした。

開発プロセスの進め方として、API仕様の検討や議論は進められるのですが、それをDocumentに落としたり、実行できる環境を準備するプロセスが後の方にある印象を持っていました。要件定義の段階で、API仕様を確定させることは難しいですが、要件定義時点で考えうるAPI仕様を策定するプロセスが少し弱いと思っています。しかし、それはメンバー同士のコミュニケーションやフォローでカバーできていたので、私自身もその良さを認識していました。 しかし、似たような課題感をチームメンバーであるa1yamaさんも持っていたようで、このような施策を実行していました。

結果的にOpenAPIを採用して、素晴らしいDocumentが出来上がってチームメンバーに良い影響を与えていました。私も出力されたAPI Documentを拝見しましたが、Backend Engineerとして、そうそう、こういうのは欲しいよね〜と感じました。 一方で、チームメンバーのヒアリングを進めているなかで、別の課題も残っているように感じました。それは、並行開発できずに開発とテストがうまいこと進められていないことでした。 前述の通り、Kyashの機能はほとんどWeb APIで実現しています。iOSやAndroidの開発はBackend Engineerがそばにいるので、話し合いながら並行開発できている状態ではありましたが、私が入ったチームが実現したい機能は、他社のチームが作ったAPIと連動して協働する必要があり、足並みを揃えることに苦心していました。それはKyashのエンジニアメンバーが持つ開発文化や進め方、品質に対する考え方と、他社チームがも持つそれとの違いから発生しているように私は感じました。 Kyashは資金移動業者であり決済事業者でもあるので、堅牢なシステムを構築するメンバーが揃っています。なので、文化や考え方はあまり違わないだろうと思っていましたが、それでも今回、一緒に協業する他社チームとは文化や考え方が少し異なっていたようで、苦労しているようでした。

前述のOpenAPIを使ったDocumentationは素晴らしい取り組みでしたが、そこから更に踏み込んだ取り組みが必要なのではないかという考えに至りました。

関心の分離

更に踏み込んだ取り組みとして、OpenAPIでAPI仕様を決めた段階でmockサーバーを立ち上げ、Mobile EngineerメンバーとBackend Engineerメンバーそれぞれで開発を進める手法を取りたいと考えました。 また、他社チームのAPI仕様を受け取った段階で、External API mockサーバーを立ち上げることにより、Backend Engineerメンバーの開発進行を阻害しないことも大事だと思いました。

なぜなら、オブジェクト指向の文脈で話される「関心の分離」ではなく、チーム間における「関心の分離」を進めたほうが、このチームはうまくいくのではないかと考えたからです。関心の分離により、開発チームがそれぞれの分野に専念できる環境を作り出し、全体の効率を向上させる狙いがあります。 Mobile EngineerはAPIの内部実装に関心を持つ必要はないし、Backend Engineerもまた、協働チームが開発したAPIの内部実装に関心を持つ必要は本来ありません。また、APIの仕様を理解しており、動くテストダブルが存在すれば、別のチームが開発するAPIの実装進捗に合わせる必要もないはずです。 他にも、別のチームが想定しているエッジケース、例えばメンテナンスによるレスポンス(5xx系)の変化や、万一の時の障害時における異常系のレスポンスを受け取った際の私達のシステムのハンドリングなど、実装はしてるけど、テストするには難しい場面は多くあります。正常系のテストだけでなく、仕様上、想定されるレスポンスに対して、どれだけ作り込まれているかを確認するためにも、テストは重要です。開発者自身もそこまで考慮してテスト設計しているのであれば、安心できるはずです。

そこで、何かいい方法でテストダブルを作れないかと思案していたら、そういえば Postman ってそういうのできるやんと思い出して深掘りしてみました。 幸い、現メンバーも過去のメンバーも、実はKyashのBackend Engineerの中にはPostmanを利用していた方が大勢いました。私もまた、E2Eテストを実装する中でPostmanを多用していました。

フロー図

関心の分離が進み、仕様に則ったmockサーバーを早い段階で作成できれば、モバイル(Android / iOS)とサーバーサイドの機能テストも個別でできるはずです。mockを使った機能テストをそれぞれで進め、最終的に結合テストやリグレッションテストでモバイルとサーバーを繋ぎこんだテストを行うほうが、テスト対象の成果物の完成度が高い状態でテスト実施できるので、テスト効率が良いはずです。そうすることで、テスト工程を開発前に持ってくることができ、Test Driven Development(TDD)やShift Leftを推し進められるのではないかと期待しています。

Postman

正直、私はPostmanについては、HTTPクライアントのGUI版で、便利にHTTPリクエストを送れるぐらいのイメージしか持っていませんでした。 もちろん、他に色々便利機能があることを知ってはいましたが、使いこなせてるとは言えない状態でした。そんな折、Postmanが connpass でワークショップを定期的に開催されているようだったので、申し込んでみました。 ワークショップが開催される前に、意識的に使い込んでみたので、ほとんどの機能については知っている状態でしたが、 mock は私のチームにうまくマッチするのではないかと感じました。

Kyashでは、テストを実施する環境として、2つ存在します。開発があらかた終わって機能テストを行う環境と、機能テストを通過して改修箇所以外に影響が出ていないか確認するリグレッションテストを行うための環境です。 連携している外部サービスによっては、公開しているテスト環境が1つしかないサービスも多く、API Gatewayの切り替えて2つの環境でテストしたり、スタブを自前で実装してテストしています。 API Gatewayを切り替えて外部サービスのテスト環境に繋いでテストできればいいのですが、例えば一意のパラメタを渡す必要があるサービスの場合、複数の環境から生成した値だと重複してしまう可能性があるため、テストできません。そのような場合、スタブを実装するのですが、外部サービスのAPIレスポンスを擬似的に返却する実装を加えるため、プロダクトコードにスタブ実装が混入してしまいます。また、スタブモードに切り替えるためにconfigなどを更新する必要があり、デプロイが必要となります。 プロダクトコードにスタブ実装が入ってしまうとあまり見通しがよろしいとは言えないし、スタブに切り替えるためだけにmerge Pull Requestを作るのも面倒です。 また、そんなに多くはないけれども、スタブの実装自体もメンテしなければならないので、コストもかかります。なので、ここをPostmanで簡単にプロダクトコードに依存しない高機能なmockを作れないか模索中です。

mock以外にも、Postmanに期待する機能があります。例えば、Postmanの Newman を用いることで、 CircleCI Orb で自動化されたAPIテストを実行できます。 Kyashでは、APIテストについて scenarigo を利用しています。 scenarigo は素晴らしいツールですが、Backend Engineerのみが扱うツールという位置づけなので、チーム間のコラボレーションは期待できません。 Postmanでリクエストを登録しておけば、コレクションを共有しているBackend Engineer以外のメンバーでも気軽に好きな環境でHTTPリクエストを送ることができ、レスポンスを確認することができるので、デバッグや動作確認に大いに役に立つはずです。 私のチームでは、OpenAPIを広めていこうとしていますので、OpenAPIをPostmanのCollectionに変換する openapi-to-postman も、チーム間コラボレーションに役に立つことを期待しています。

Kyashをリリースしてから10年が経過し、それまで様々なエンジニアが実装してきたAPIには膨大な数のendpointが存在します。中には必要なのかそうではないのかわからないものも存在するなかで、APIテストを浸透させていくためには、Backend Engineerの方々の協力が不可欠です。 PostmanのCollectionを増やしていけば、Backend Engineerが触れたことのないendpointの動く仕様も簡単に手に入れることができるため、開発効率に貢献できるので、協力を得やすいと思っています。結果的に、APIテストの浸透を加速できるのではないかと期待しています。

現在は、私達のチームで利用するmockをPostmanで実現できないか検証しつつ、クライアント(Android / iOS)からコールされるAPIリクエストを確認し、E2Eテストの自動化を進めています。

ちょっとみせ

Postmanをチームに広めていくに当たり、「こんなことができるんだよ」とレクチャーしたほうが良いと考えたので、いくつかAPIテストを作ってみました。 その中で、以下のようなスクリプトを実装しました。

const luhnCheck = (number) => {
    let sum = 0;
    let shouldDouble = false;
    
    // 右から左に向かって数字を処理
    for (let i = number.length - 1; i >= 0; i--) {
        let digit = parseInt(number.charAt(i));
        if (shouldDouble) {
            digit *= 2;
            if (digit > 9) {
                digit -= 9;
            }
        }
        sum += digit;
        shouldDouble = !shouldDouble;
    }
    return (sum % 10 === 0);
}

module.exports = {
    luhnCheck
}

Postmanでは、 PackageLibrary を利用して、Node.jsベースの独自のJavascriptでテストコードを書けます。 上記の luhnCheck は、引数として渡された数値列がLuhnアルゴリズムによるチェックディジットとして正しいかチェックする関数です。これを利用して発行されたクレジットカード番号が正しいかチェックするAPIテストを実装しています。 また、Kyashはクレジットカード業界に属しているので、様々な暗号化方式を利用しています。暗号化した文字列を復号化する処理を様々な場面で利用していますので、比較的簡単にPackage LibraryにJavaScriptで実装できるのは嬉しいポイントでした。

おわりに

Software Engineer in Testとして入社してから、モバイルアプリのUIテスト自動化に取り組み、Backend EngineerとしてAPIのプロダクト開発に参加し、QAとして戻ってきました。 私はソフトウェア品質を高めていく活動を進めているのですが、すでに出来上がっているプロダクトのソフトウェア品質を高める活動には、メンバーの協力が欠かせません。そのため、活動を浸透させるための仕掛けを入念に設計し、粘り強く普及させる必要があります。そうしなければ、せっかく良い取り組みや活動が風化し、意味を失ってしまうと考えています。 とはいえ、メンバーにAPIテストを実装してもらうにしても、スイッチングコストが高くなってしまい、なかなか受け入れてもらえずテストコードが増えていきません。そうすると、テスト実装コストはQAが受け持つことになり、QAメンバーの負荷が上がり、どちらにしても結果的にテストコードが増えません。Backend Engineerの開発に必要(便利)なツールとして開発プロセスにCollectionの追加を組み込み、自然とテストコードが増えていく事が理想だなと考えていますので、すでに各々で使っているPostmanをうまく利用しない手はないと思っています。 そのために、私が率先してPostmanをうまく使いこなせるようになることで、TDDやShift Leftを実現したいと考えています。

テストや品質的な話をすると、どうしても面倒に感じてしまうし後回しにしがちだと思います。実際、私が開発してても同じ思いを持つ機会も多いです。でも、急がば回れではないですが、その時点で考えうる仕様を決めてしまい、動くmockサーバーを作ってしまってメンバーの手が止まる機会を少しでも少なくすれば、高品質な成果物がもっと早く出来上がるのではないかと思っています。

明日の投稿もぜひお楽しみに。バイバーイ。