Tabelog Tech Blog

食べログの開発者による技術ブログです

テストケースファーストでいこう

この記事は 食べログアドベントカレンダー2022 の17日目の記事です🎅🎄🎁🍗

こんにちは!食べログでサーバーサイドエンジニアをしている清水です。
みなさんテストケース書いてますかー?

テストケースといえばテスト実施の直前に作成するものだと考えている方もいるかもしれませんが、
私が所属するチームでは実装に着手する前の設計段階で作成する取り組みを行っています。
(記事の執筆にあたり勝手に テストケースファースト と命名しました!)

本記事ではこの取り組みの背景やメリットなどについて紹介します。
なお、本記事におけるテストケースとは結合テストケースのことを指して記載しています。

背景と課題

少し話が逸れますが、私はもともとSIer出身で数ヶ月程度の案件をウォーターフォールモデルで開発することが多い環境でした。
当時は設計書をお客様に納品する成果物として厳しくチェックされ、日本語の使い方など肝心のプログラム以外の部分で多くの時間が掛かっていたことを覚えています。
また、設計後の手戻りが起きないように工程管理も徹底されていました。

それに対して食べログでの案件規模は様々で、短い案件は数日で終わり長い案件でも2〜3ヶ月で終わるものがほとんどです。
そのため案件に応じてドキュメントの記述レベルを変えるなどSIer時代と比べて柔軟な開発を行っています。
例えば数日程度で終わる案件については設計書に方針のみを記載し、詳細設計は実装ベースで進めることが多いです。

食べログ内には様々なチームがあり担当する分掌が異なるため、それぞれの特色に合わせてやり易いように開発の進め方は異なります。
その中で私の所属するチームは業務目線が強いため、要件定義や設計をしっかりと固めたウォーターフォールモデルでの開発を基本としています。
SIer時代と比べると開発フロー自体は変わっていませんが、ドキュメントの粒度や実装までのスピード感は大きく変わったと感じています。

このように案件によって柔軟な進め方ができることや開発のスピード感が増したことは私が食べログに入って嬉しいと感じたポイントですが、設計書の粒度を荒くしすぎてしまうことで開発時に次のような問題が起きることがありました。

  • 設計時には開発者とレビュー者の認識が合っていた(つもりだった)が、実装が完了した段階で認識齟齬が発覚した
  • 実装やテスト工程において設計や要件定義の考慮漏れが発覚したため実装を見直すことになった

実際に私も設計書のレビュー時に「設計書には書いていないけど実装でカバーしてくれるだろう」と勝手に期待を込めてOKを出してしまい、実装が終わってから期待通りになっておらず指摘するような経験がありました。

図にするとこのようなイメージです。

これは考慮漏れによって手戻りが発生していることを説明した画像です。

ひょっとすると似たような経験のある方もいるのではないでしょうか・・・?

特にメンバーが新規参入した直後などドメイン知識がなく開発に不慣れな状態の場合、これらの認識齟齬や考慮漏れが多く発生し手戻りに繋がる恐れがあります。 参入早々で右も左もわからない状態なので当然のことですよね。

食べログは15年以上運用されてきたサービスということもありシステム間の依存関係や業務を理解するためには時間が掛かります。

私が所属しているチームが担当する店舗会員領域は主に飲食店の管理者向けの機能を軸としており、それを取り巻くカスタマーサポート・営業・販売管理・情報拡充サポート・販売代理店など多くの社外関係者が存在します。このように多くの方の業務が関連しているため、1つの機能の改修であってもそれら関係者の業務影響を考慮する必要があります。
また、店舗会員の種別や契約プランの種類によって動作を変えている機能が多いため、これらの考慮を見誤ると業務を止めてしまう障害や正しい機能を提供できない障害に繋がるわけです😱

このような背景もあり要件定義や設計でしっかり業務影響を洗い出す必要があるのですが、かといって上流工程に多くの時間を掛けるとリリースが遅くなる懸念もあります。 これではスピードと品質を天秤にかける状態になってしまいますね⚖️😇

そこで開発スピードを落とさず手戻りを少なくする方法として「設計後にテストケースを作成する」ように開発フローを変更する試みを行いました。

テストケースファーストのやり方・考え方

テストケースファーストのやり方は非常に単純で、これまでの開発フローの結合テストケース作成タイミングを設計〜実装の間に変更するだけです。(もしくは設計に含めても可)

[これまでの開発フロー]
・設計 → 実装・単体テスト → テストケース作成 → 結合テスト

[変更後の開発フロー]
・設計 → テストケース作成 → 実装・単体テスト → 結合テスト

これまでの開発フローではテストケースを作成するのが実装後のタイミングであったため、その際に設計の考慮漏れが発覚すると手戻りが大きくなってしまいました。 変更後の開発フローでは実装前にテストケースを作成するため、設計の考慮漏れを早期に発見することができます。また、開発担当者の仕様理解が深まり実装のイメージが湧きやすくなるメリットもあります。

例えば以下の例の赤枠部分のように大枠だけでも先に担当者とレビュー者の認識を合わせておくことで手戻りを未然に防ぐ効果が期待できます。

これはテストの大項目中項目にハイライトを当てた画像です。

実際に案件を進める際はテストケース作成の前にテスト観点を洗い出すと思うので、テスト観点からレビューしてもらうとより安心ですね。
また、レビュー者としては情報がマトリクスで整理されているため仕様理解がしやすいと思います。

このようにテストケースファーストの開発フローを通して、担当者の心理状態も以下のように変化したと感じています。

これはテストケースファーストの開発フローを行った場合の画像です。

これまでテストケース作成時に発生していた大幅な手戻りがなくなることで担当者も安心して実装工程以降に進むことができるようになりました!

ここまで読んで「実装よりも先に結合テストケースを作れるの?」という疑問を持つかもしれませんが、今のところ問題なく作ることができています。 その理由はウォータフォールモデルのV字モデルで考えるとわかりやすいです。

これはウォータフォールモデルのV字モデルを説明した画像です。

この図を見ると基本設計の検証は結合テストで行われるということがわかります。 つまり基本設計が終われば結合テストケースの作成は可能ということです!

また、テストケースファーストと似たような考えとして「テスト駆動開発(TDD)」がありますが、テストケースファーストではテスト駆動開発とは異なり実装前のテストコード作成は求めないことにしました。

なぜなら私は前職でテスト駆動開発を経験したことがありますが、スタブやモックの使い分けなどテストコードを書くためのスキルが必要だったり、データ作成に難航したりと思ったよりもスムーズに進まないことが多く苦労したためです。また、一度書いたテストコードをメンテナンスしていく必要もあります。

先述したように食べログの店舗会員領域は関係者が多いため、テスト範囲も広く完全なE2Eでのテスト自動化は想像しただけで骨の折れる話でもあります。。。(できたら素敵ですがCI導入は効果的なポイントに絞って行うのが良いと考えています)

それに対しテストケースファーストでは成果物はこれまでと変わらず、テストケースの作成タイミングを変えるだけなので既存の開発プロセスに組み込みやすいメリットがあります。

実際にテストケースファーストをやってみて

このテストケースファーストの取り組みを通して、当初は実装する側だけのメリットを考えていましたが実際はレビューする側にとってもメリットがあったと感じています。
私がこの取り組みを通して感じたメリットを「開発担当者の視点」と「レビュー者の視点」それぞれでまとめてみました。

開発担当者の視点

  • 要件定義や設計の考慮漏れを早期発見することで実装後の手戻りが少なくなった
  • 実装する機能のイメージがより明確になったため実装での迷いが少なくなった
  • 外部接続などが必要な点が事前に洗い出されるため開発の段取りが立てやすくなった(後工程で行うことが明確になり見積もり精度も上がる)

レビュー者の視点

  • 操作と結果をマトリクスで見られるため仕様理解しやすい(設計書を理解するための手助けにも有効)
  • 条件や観点が網羅されているかチェックしやすい(考慮漏れに気づきやすい)
  • 担当者の仕様理解度を把握する指標になる(テストケースを作れる=仕様を理解し設計に落とし込めている状態)

このように開発担当者とレビュー者の双方にとって大きいメリットがあったと感じています。
特に私が思うのは、早い段階で結合テストケースのレビューまで完了させておくとその後の開発の 安心感が半端ない です!
まるで夏休みの宿題を早く終わらせたかのような余裕があります(笑)

むしろこれまで開発担当者が結合テストのシナリオが描けていない状態で実装に着手していたことがおかしかったのですが、結局それに気付くタイミングは実装が終わってからだったんですよね。
テストケースを先に作ってレビューするというアプローチは、実装に着手するための許可証(通行手形)を確認するような当たり前の考えなのかもしれません。

ただしすべての開発においてこのテストケースファーストが効率的かというとそうではありません。
例えばプロトタイプモデルのような要件が固まっていない開発では、テストケースの修正頻度が高くなってしまい手戻りが大きいためです。

また、その他のデメリットとしては実際に動くものを見られるのが遅くなるため、レビュー者や企画者などと視覚的な認識合わせができない点があります。 案件によっては言葉で説明するよりも試作品を作って認識合わせをした方が進めやすく、実装から始めた方が良い場合もあります。

実際に私が所属するチームでもプロトタイプモデルでの開発をすることもあるので、テストケースファーストの徹底はしておらず案件ごとに臨機応変な対応を行うようにしています。

また、これを言ったら元も子もないですが開発者なら「テストケースを書くよりも早く動く物を作りたい!」「実装の方が楽しい!」という気持ちもすごくわかります。

とにかく大事なのは既存のアプローチに捉われずに自分達が開発しやすいように改善していくこと、そして開発を楽しむことだと感じました!

まとめ

私のこれまでの開発経験から「テストケースはテストの実施直前に作成するもの」という考えが刷り込まれていたため、テストケースを実装よりも先に作るという考えは盲点でした。

規模の小さい案件でスピード重視となるとつい設計の粒度を落としてしまいがちですが、この流れであればテストケース作成時に必要な観点の洗い出しができるため、手戻りが少なく開発を進められると考えています。

また、この取り組みを通して得られた効果は当初想定していた「開発担当者の理解が深まり実装後の手戻りが減った」だけでなく「開発担当者とレビュー者の双方が安心感を得た状態で案件を進められる」点も非常に大きいと感じました。

テストケースファーストはすべての開発手法において有効な手段というわけではありませんが、要件が固まっている案件で開発者の理解を深める目的では非常に有効だと感じています。

既存の開発プロセスを大きく変えることなく簡単に取り入れることができるので、気になる方はぜひ試してみてください!

明日は @mew3880 の『食べログの新卒エンジニア1年目が考える「学生時代にやっておけば良かったこと」について』です。お楽しみに!