Upgrade to Pro — share decks privately, control downloads, hide ads and more …

NEWT Backend (GraphQL) の自動テストの現状とこれから ~ 2年間の開発・...

NEWT Backend (GraphQL) の自動テストの現状とこれから ~ 2年間の開発・運用で遭遇した課題と工夫、今後の課題 ~

NEWT Tech Talk vol.10 チームで品質に向き合うエンジニアとQAそれぞれの取り組み
https://reiwatravel.connpass.com/event/321544/

Shumpei IINUMA

July 25, 2024
Tweet

More Decks by Shumpei IINUMA

Other Decks in Programming

Transcript

  1. 2024-07-25 NEWT Tech Talk vol.10 Shumpei IINUMA ( 株式会社令和トラベル) NEWT

    Backend (GraphQL) の自動テストの現状とこれから ~ 2 年間の開発・運用で遭遇した課題と工夫、今後の課題 ~
  2. Shumpei IINUMA 令和トラベルでバックエンドエンジニアをしています 新しい旅行を体現するアプリ「NEWT 」と、それを提供 するための旅行管理システムのAPI やインフラの開発 ~ 2015 大学院で自然言語処理を学ぶ

    2016 ~ 2017 リクルートでサイト内検索ロジックの開発 2017 ~ 2021 SaaS プロダクトの開発 2022 ~ 令和トラベルにジョイン 主な仕事内容 略歴 @iinm_stderr @iinm
  3. 前提:バックエンドチームの主な活動領域 Public Endpoint Private Endpoint Admin NEWT Android Team iOS

    Team Frontend Team Backend Team API 社内向け ツアー企画・手配業務 カスタマー向け 海外ツアー・ホテル予約 今日話す「自動テスト」の対象
  4. テストサイズによる分類 Large ( それ以上の環境) Medium ( 単一マシンで実行可能) Small ( 単一プロセスで実行可能)

    Large :開発環境にデプロイしてテスト UI から操作するテスト 負荷テスト Medium :Docker 上のDatabase を利用したテスト Small :単一プロセスでのテスト GraphQL エンドポイントのテスト ※GraphQL 以外のHTTP エンドポイントもある 外部システムはテストダブル エンドポイント単位ではパターン網羅が大変 なので処理を切り出した部分のテスト 「ツアーの料金計算」など、プロセス外に副作用 のないロジックのみのテスト API の自動テスト 実行コスト
  5. テストサイズによる分類:API 自動テストのサイズごとの比率 Large N/A Medium 718 files Small 146 files

    GraphQL エンドポイントのテスト (60%) それ以外のテスト (40%) 大部分が、エンドポイント単位でのテスト または データベースアクセスとの通しでのテスト 特にパフォーマンスが重要な機能の改修時 シナリオを書いて負荷テストをしている File の単位 Medium: エンドポイント単位 Small: 関数 テストケース数:合計5,450 ケース
  6. 課題:テストが全体的に読みづらい 🤔 テストコードをレビューするタイミング タイトルでテスト観点を明示するところまでは当然やったうえでの話 前提条件となるデータのセットアップ、実行、検証が煩雑で、どこがポイントなのかが 分からない。 工夫: Given-​ When-​ Then

    記法:セットアップ、実行、検証のフェーズを明記 開発メンバーの中にSpock Framework の利用経験者がいて 提案してくれた。 コメントではなく、記載を強制で きるライブラリもある。
  7. 課題:期待値の視認性が低いケース 👀 例:ツアーの旅程表の生成結果 (数百行続く) 出力が巨大なJSON のパターン 期待値のサイズが大きすぎて、正しい 結果であることを確認することが難し い。 期待値を直接書くのではなく、Jest

    の Snapshot 機能を使って書き出された結 果を目視でチェックしていた。 ある日、チェックしきれずに不具合を 含んだまま本番にリリースされること に 😱
  8. 課題:有効なテストデータになっているか? 例えば ツアーの予約をテストするには、ツアーが必要。 ツアーを作るには、フライト、ホテルなど様々な依存データの設定が必要。 毎度セットアップするのは大変なので、データセット作成用の関数を用意している。 何が問題か? データセット作成用の関数がDatabase に直接insert していた場合、バリデーションを通してない ので、本番環境にはないような不正なデータでテストしている可能性がある。

    例えば、特定日の在庫を0 に書き換えるなど、データセットの一部設定を書き換えてテストに利 用することがある。この際、自分が作ってない(詳しくない)モジュールのテーブルを直接書き 換えることがある。詳細を調べるのに時間が掛かるうえ、使い方を誤る危険性がある。(実際に これ起因で致命的不具合が生じたことはまだないが)
  9. テストの並列実行とデータクリーンアップの高速化 Test worker process ごとにDatabase を用意することでクリーンアップタイミングを 気にせず並列実行可能に。 ※ テストを実行するマシンの台数を増やす方法もあるが、マシン ごとのセットアップ処理の重複の無駄が無視できないレベルになる。

    テスト中のデータベースアクセスを記録して、利用したテーブルのみ自動でtruncate するこ とでデータクリーンアップを高速化。 方法 Machine #1 Database process on Docker Test worker #1 Test worker #2 Test worker #3 Test worker #4 Test database #1 Test database #1 Test database #1 Test database #1 x N 台 参考 テストファイルの総数は864 件 (5,450 件のテストケース) GitHub Actions 上の 8 core / 32 GB Memory のマシン4 台で15 分 で実行可能
  10. サマリー:NEWT Backend (GraphQL) の自動テスト 大部分をMedium サイズのGraphQL エンドポイントレベルでテスト 最低限のテストダブルで実装の詳細に依存しすぎないテスト 方法 Given-​

    When-​ Then 記法の活用 人が読みやすいSnapshot テスト マルチコアを有効活用できる実行環境 工夫ポイント 効率良く有効なテストデータをセットアップする仕組み 開発環境 / 本番環境に対する自動テスト Medium サイズのテストの実行速度 / 実行スコープの制御 (あるいはシステム分割) 今後課題