はじめまして
システム本部旅行メディアシステム部のツネイと申します。
先日6/20に、担当している「価格.com 旅行・トラベル」がちょうど1st anniversaryを迎えたので、サービスの紹介がてら、立ち上げの頃に導入した自動テスト周りについて書きたいと思います。
自分自身も価格.comのアーキテクチャ自体についてはまだまだビギナーの頃で、(当時)部門内で自動テストの文化もこれからの中で心機一転やってみた。の結果の体験談として眺めていただけると幸いです。
「価格.com 旅行・トラベル」is何
現在提供中の第一弾の商材としては旅行サイト複数社の国内宿泊施設の宿泊プランについて、一括検索・比較を提供しているメタサーチサイトです。
膨大な数の日別のプラン・在庫に対して、エリア・宿タイプ・こだわり条件といった多様な切り口での検索を実現するために、フロントエンドのWebからはAPIを介して、バックエンドの検索エンジンを使っています。
4travel、icottoといった、カカクコムグループ内の他の旅行メディアも使用している横断的な検索エンジンで、大きくバックエンドとフロントエンドで2分割すると、わりと疎結合な形で構成されています。
※初期構築時は、そもそもフロントエンド⇔バックエンドで別部門でした。
背景
新興サービス。特にフロントWeb領域はゼロスタートなので、既存カテゴリの悩みどころのClassicASPの混在などがなく、一気通貫で導入しやすそうだった
いいね!と言ってポジティブにトライをしてくれるメンバーに囲まれていた(ここが一番大きいかな!!)
上記のような背景や縁もあり、地の利・人の利に恵まれた幸せ者です。感謝。
リリース後の現状
Testing PyramidやTesting Trophyといったガイドラインで紹介されているレイヤーに当て込むとすると、最近は下記の具合です。
E2E
モックを使わずに、各所(検索API、SNS連携、GoogleMap...)実際に疎通してテストを実施しています。
初期はPlaywrightでテストプログラムを用意して実行していましたが、SaaSのmablを現在は使っています。 ローコードによるテストの構築が特徴ですが、フローの設定やJavaScriptスニペットを活用できるので、Playwrightとの間でのできること⇔できないことは特になく、スムーズに移行は出来ました。
E2Eテスト自体によく言われるように実行コストが高く、壊れやすいのが特徴で対象ケースはある程度厳選した方が良いです。 「価格.com 旅行・トラベル」で行くと、一覧の検索機能・旅行サイトへの送客のような、ユーザー価値の高い操作を選ぶようなイメージでやっています。 実行・メンテコストも跳ね上がり、良いことは無いので、細かいバリエーションのロジック確認はここで行わず、挙動ベース(≒ブラックボックス)でクリティカルな箇所を検出する目的です。
※特に文脈に関係の無い、私物のオリエンタル色の強い素敵な mabl Tシャツです。
Integration、統合、結合テスト
テストの対象範囲に応じて必要な箇所をモックした上で、コンポーネントを組み合わせてテストを行っています。 フロントWeb側の目線の一例で行くと、モックのHTTP RequesterをDIして、検索APIへのリクエストを介する周辺コンポーネントの連動を確認したりします。
検索APIのモック部分ではjsonを用意して、実際の検索処理を動かさずに静的なレスポンスを返してテストを実施しています。
開発最初期に用意したので、フロントエンド⇔バックエンドの並行開発にも効果があり、工数を圧縮できました。APIが びた一文 完成していなくても、独立して画面の開発を進行可能です。 IFだけすり合わせておけば、お互いに影響せず開発も疎結合で進みますし、何より実際のjsonレベルでの具体的なIFのすり合わせが要求されるので、矛盾の検知は早く、手戻りも少なかった印象です。
順番的に初期はこの領域のテストが多めだったと思います。
※部門が別だった時代のお絵描き。1部⇒今のフロントエンド領域 5部⇒今のバックエンド領域 で、まだ分かれていた時代です。
Unit、単体テスト
単一のコンポーネントに対してホワイトボックスなテストを行います。 テストの実装をルール化していると手動のテスト仕様書よりもごまかしが利かず、単一機能の定義をハッキリさせなければいけないので、これも手戻りの少なさ(普段の品質向上)に貢献してくれたと思います。 「正常にチェックされること」「異常値の場合にエラーが返ること」のような曖昧なテスト基準では、テストコードは書けません。
また、実装者の意図がはっきりわかるテストコードが一緒にあると、普段のコードレビューがとてもしやすかったです。仕様の勘違いの検出も手前に来やすかったです。
Static、静的解析
SonarQubeの活用を始めていますがまだまだこれから。です。 コード品質の一定化と、主観に依らない客観的なコードレビューの補助になってくれることを期待しています。数値って大事です。 (重複度はどのぐらい、複雑度はどのぐらい、順序的にまずどこを。 ⇒ 改善も当てずっぽうや感覚でやってはいけません。)
DevOpsチームと良い感じで連携してパイプラインに組込めると、happyなんじゃないかと思っています。
おまけ:カバレッジ
トータルでラインカバレッジ:85%、ブランチカバレッジ:75%前後を最近は推移しています。 テストの書き方に依るとは思いますが、ブランチカバレッジの方を目安としては重視して観測しています。 assertがない・意味の薄いassertで単に実行しただけのカバレッジではあまり助かりませんし。(実行時エラーの検出とかはそれでも出来ると思います)
むやみにカバレッジの数字を100%に近づけるよりは、QCD的には今時点良い塩梅の体感ですが、状況に応じて都度良い感じに運用したいと思います。 費用対効果が大事です。テストを書くために頑張るんじゃなくて、効率よく安定するために頑張ります。
すごく大事なテストの実行速度は2500件ほどのテストショットで3分弱ぐらいなので、許容範囲かと思います。
感想
やる前から分かっていたけれど、人間よりも機械の方が怠けず、勤勉で正確なので、定型の繰り返し作業は機械に任せて、自動化したほうが圧倒的に有利だとあらためて思いました。
全部がそうとは思いませんが単純なリグレッションテストなど、自動化で置換可能な手動作業に対する労力・努力は、揮発性なことが多いと思います。(手動テストはゼロにできないし、必要な手動テストはあるので全部ではないです。) 時間は有限なので、人間にしかできないクリエイティブに対して、メンバーには引き続き時間を割いていただきたいです。また、そういうチームにしたいです。 効率化して時間が空いたら、ワークライフバランスの改善でも素晴らしいこと!
自動テストについてピックアップして書きましたが、新規サービスに関わらず、大き目のプロジェクトはバランスも大事だと思います。 一カ所だけに拘らず・凝りすぎずにうまくパワーを配分すると良いと思います。 (不要な要件+素晴らしい設計・開発・テスト=素晴らしい不要品。になっちゃいますし。QCDを考えて最大の効果が出せるバランスが重要かと思います。)
これから
「価格.com 旅行・トラベル」は機能や領域を鋭意拡充予定です。 最初の構築より、リリース後にうまく回して発展させる運用の方が、システム開発は大変だと思います。
テストも積もるだけだと遅くもなるし、動きも鈍ります。 足し算でどんどん無駄に太らせずに洗練させていきたいと思っています。でないと逆にテストの維持コストで首が絞まる・足を引っ張りそうです。
とはいえ、まだまだ効率化したい部分はたくさんあります。 既存資源のPlaywrightを使ってスクリーンショットの撮影をさせれば、何かと組み合わせて効率的なビジュアルリグレッションテストはできないだろうか。だとか、いろいろやってみたいことはあるのでまた機会があれば!
カカクコムでは共にサービスをつくる仲間を募集しています
「価格.com 旅行・トラベル」はWin/OSS、C#/PHP/Rubyといった多彩な技術を駆使したフィールドの広いサービスです。 また、まだ1st anniversaryという鋭意拡充中のタイミングで、一緒にこれからサービスをつくっていただける人財を絶賛募集中でございます。
直近ではChatGPTのプラグインの開発など、日々賑やかに過ごしています。
「価格.com 旅行・トラベル」でもそれ以外でも、ぜひぜひご興味のある方はこちらをご覧ください。