コードを書き始める前からテストをずっと考える ─ 継続的テストモデルとシフトレフトなテスト活動をアジャイルにどう取り入れるか

継続的テスト continuous testing シフトレフトな活動をアジャイルにどう取り入れるか

読者の皆さんは、テストについてどのようなイメージをお持ちでしょうか。「開発の後に行う確認作業」といったイメージを持たれている方もいるかと思います。

しかし、開発しようとしているソフトウェアに不具合の混入を防ぐには、もっと早い段階でテストについて考えることが必要です。こういったテスト活動は、プログラムを1文字も書いていないときから始めることができるのです。

本記事では、2016年に提唱された継続的テストモデルを紹介しつつ、アジャイルとも親和性のあるシフトレフトなテスト活動について解説していきます。

DevOpsにおけるテストの考え方

継続的テストモデルは、主にDevOpsの世界におけるテストの考え方の1つです。そこで継続的テストモデルを説明する前に、DevOpsの考え方と「DevOpsのループ図」について解説します。

DevOpsとは「開発(Development)」と「運用(Operations)」を組み合わせた造語です。2009年10月にベルギーで開催された「DevOpsDays」というイベント名に由来しており、この経緯は次のドキュメントなどで紹介されています。

The Incredible True Story of How DevOps Got Its Name

それまでの開発と運用の関係では、「開発担当の仕事は新機能を開発すること」「運用担当の仕事は開発されたプロダクトを安定して運用すること」という考え方がほとんどでした。ときには両者が対立することもありました。

それに対してDevOpsでは「運用のことを考えて開発を行っていく」「開発のことを考えて運用を行っていく」という考え方をします。例えば、「運用がしやすい形の開発はできないか?」「次の開発につながる運用はできないか?」といったことを考えます。DevOpsでは、担当者間の垣根をなくし、うまくやっていくことを大切にしていると言えます。

これは、DevOpsDaysの創始者であるPatrick Debois@patrickdeboisが、DevOpsDays Tokyo 2021に出演した際に「どのテクノロジーを使っているかではなく、担当者間のギャップを埋めることがDevOpsである」「『DevOps=自動化』と結びつける意図はなかった」といった発言をしていることからもうかがえます。

Q&A with Patrick Debois around devops - Devopsdays Tokyo 2021 - YouTube

DevOpsのループ図とは何か?

開発と運用がうまくやっていくDevOpsの考えを表現したものとして、DevOpsのループ図があります。定かではありませんが、2013年に書かれた「DevOps Scares Me – Part 2」という記事が初出ではないかと言われています。

初出と思われる記事に載っているDevOpsのループ図

この図では左側が開発で右側が運用の領域になりますが、開発と運用が完全な別チームとして動くのではなく、お互いにフィードバックするため連携して動くことの大切さを表しています。

継続的テストモデルとは何か

継続的テストモデルは、ロンドン在住でQAの専門家であるDan Ashby@DanAshby04が2016年に次の記事で提唱しました

Continuous Testing in DevOps…

Danは、DevOpsの世界の中でテストがどのような位置づけにあるのかを次の図で説明しました。

Danの提唱する継続的モデルの図(日本語訳は筆者による)

これは、先ほど紹介したDevOpsのループ図をもとに、ビルドの後だけでなくどのプロセスにおいてもテストを実行できるというDanの主張を入れたものです。

継続的テストモデルにおいてテストは「活動」である

「テストの目的は何か?」と聞くと、「開発したものが正しく動いているか確認するため」「仕様通りに動いているか確認するため」という回答をもらうことがよくあります。こういった思考になる背景として、「テストより開発が先にある」「開発が終わったら、やっとテストの出番だ」と考えられているかもしれません。これは、テストを開発におけるフェーズの1つとして捉えている結果とも言えます。

一方、継続テストモデルでは、テストを1つのフェーズではなく、常に行うことができる活動(アクティビティ)として捉えていると言えるでしょう。それを表したものが、先ほどの図になります。

シフトレフトなテスト活動とシフトライトなテスト活動

テストをフェーズとして捉えている場合、継続的テストモデルでいう「MERGE」や「BUILD」の部分のみでテストを行うことを前提としていることが多いでしょう。Danの図でみるなら次の範囲だけになりがちです。

よくあるテストのイメージ

しかし、実際の継続的テストモデルでは、MERGEやBUILDに限らず他のどのタイミングでもテストを考えられることを示唆しています。

ここでMERGEやBUILDを基準に考えて、より左側(前の段階)である「CODE」や「PLAN」「BRANCH」の部分でテストすることを「シフトレフトなテスト活動」と呼びます。一方、より右側となる「RELEASE」以降の部分でテストすることを「シフトライトなテスト活動」と呼ぶことがあります。

本記事では、テストをフェーズから脱却させる際に、最初に取り組みやすい「シフトレフトなテスト活動」について具体例を交えて紹介します。

シフトレフトなテスト活動としてのテスト駆動開発

近年はより多くの組織で採用されるようになってきた「テスト駆動開発(Test-driven development、TDD)」ですが、これもシフトレフトなテスト活動の一例と言えるでしょう。先ほどの継続的テストモデルの図に当てはめるなら「CODE」前後のテスト活動と捉えることができます。

テスト駆動開発については多くの記事で語られているので、本記事では説明を割愛します。詳しく知りたい方は「TDD Boot Camp 2020 Online #1」の和田卓人@t_wadaさんによる基調講演の動画をご覧ください。

TDD Boot Camp 2020 Online #1 基調講演/ライブコーディング - YouTube

コード実装を始める前から行うテスト活動

本記事では「CODE」より前になる「PLAN」や「BRANCH」の部分におけるテスト活動について紹介します。

例えば、「会員登録画面で設定できるユーザー名は、4文字以上12文字以下で英数字のみを許容するように修正する」という開発チケットがあったとします。これに対して、どのようなテストが考えられるでしょうか。

チケットに書いてある修正内容から、以下のようなテストが考えられるでしょう。

  • ユーザー名の文字数に関するテスト(4文字以上12文字以下)
  • ユーザー名の文字種に関するテスト(英数字のみ)

しかし、それだけではなく、以下のような状況も考えることができます。

  • 許容できない場合(例えば15文字を入力した時)、画面上どうなるのか?
    • 会員登録を実行した後でエラー画面に遷移するのか
    • それとも「会員登録」のボタンが押せない(非活性になる)のか
  • 修正前から「4文字以上12文字以下の英数字のみ」ではないデータが入っていたとしたらどうなるのか

このように、開発チケットに書いてある「文字数」「文字種」といった内容をなぞるだけでなく、書かれていない部分でテストすべき気になる内容を挙げていくことが大切です。

シフトレフトなテスト活動は不具合の混入を防ぐ

先ほどの修正チケットの事例で、文字数制限などが許容できないケースに注目してもう少し詳しく考えてみましょう。

普段の業務ではチームで開発しているとします。例えば、会員登録画面を開発者Aさんが実装しており、エラー画面を開発者Bさんが実装しています。設計時点では、それぞれが心の中で以下のように思っているかもしれません。

Aさん(エラー画面はBさんが作ってくれるだろう。)

Bさん(この部分はAさんがボタンを制御してくれるだろう。なので、他のエラー画面を実装しよう)

このまま実装が終わり、テストを実行するとどうなるでしょう。遷移先のエラー画面がないため、不具合を起票することになります。

一方で、設計時点(継続的テストモデルでいう「PLAN」の時点)で、以下のような会話をしているとどうなるでしょうか?

Aさん「許容しないケースが入力された場合、どうする?」

Bさん「エラー画面を作ることにしようか」

QA「そしたら、ちゃんとエラー画面に遷移するかテストするね」

こうなれば、テスト実行時点で「エラー画面に遷移しない」という不具合は出てこない可能性が高いです。なぜならば、設計時にこのような会話をしておくことで、否が応でもエラー画面について意識して実装をするためです。つまり、不具合の混入を防ぐことができるのです。

不具合の混入を防ぐことは、総コストの削減に繋がる

不具合を起票する場合、通常は新たに以下の追加コストが発生します。

  • 不具合のチケットを起票するコスト
  • どのような開発をしていたかを思い出すコスト
  • 修正を行うコスト
  • 不具合発見時と同じテストを行うコスト
  • 周辺の似たような機能についてのテストを行うコスト
  • 起票したチケットを完了にするコスト

不具合の混入を防ぐことは、これらの追加コストを抑えることができます。

このコストは、想像以上に大きいです。NIST(アメリカ国立標準技術研究所)の論文「The Economic Impacts of Inadequate Infrastructure for Software Testing [PDF]」では、以下のグラフのようなコストの相対比があると主張しています。

ソフトウェア開発の各段階で発見された欠陥の修復にかかるコストの相対比(左端の設計を1とする)

「PLAN」や「BRANCH」の部分でテスト活動を行い、不具合の混入を防ぐことで、上のグラフのできるだけ左側でコストを支払うようにしています。結果として、総コストの削減につながります。

プログラムを1文字も書いていないときからテスト活動を行いうる

ここで改めて、先ほど紹介した修正チケットの事例をよく読んでみてください。ここまでの話でプログラムは1文字も出てきていません。これがまさに、シフトレフトなテスト活動の1つ、コード実装を始める前から行うテスト活動の例です。

シフトレフトなテスト活動と聞いても、これまであまりイメージが湧かなかったかもしれません。まずは今回の例のように、設計の時点からテストを考えてみることをオススメします。

実際の業務では、設計レビューの際などに「どのように実装するか」という議論に加えて、「何をテストすべきか」という議論もあわせて行ってみるのはいかがでしょうか。

スクラムにおけるシフトレフトなテスト活動のタイミング

継続的テストモデルでいう「PLAN」や「BRANCH」で行うシフトレフトなテスト活動は、アジャイルなソフトウェア開発においてどのようなタイミングで行うとよいのでしょうか。

例えばスクラムにおいては、プロダクトバックログアイテムのリファインメントのタイミングで行うことをオススメします。リファインメントについて「スクラムガイド [PDF]」では、以下のように述べられています。

スクラムチームは通常、リファインメントの活動を通じて、選択に必要な透明性を獲得する。プロダクトバックログアイテムがより⼩さく詳細になるように、分割および定義をする活動である。

今回紹介した会員登録の事例は、テストを考えることを通じて、これから作ろうとしているものをより明確にしています。つまり、プロダクトバックログアイテムの透明性を獲得するような活動そのものであり、リファインメントでの目的そのものと合致します*1

リファインメントでのテスト活動を促すためのコツ

「リファインメント時にテスト活動をしよう」と意気込んでも、いざやってみようとすると、どのように行えばよいか分からないかもしれません。これは経験や慣れが必要な世界だと思います。そんな中でも実践できるコツとして、有効な問いかけを1つ紹介します。

「この開発チケットによって、アプリ上の振る舞いはどのように変わりますか?」

開発するにあたって、コード実装の中身についての修正方針は明確にされている一方で、アプリケーションの振る舞いがどのように変化するのかは明確になっていないことがよくあります。そんなときに、この問いかけは有効です。

開発の不確実性に連動してテスト活動も継続的に行う

通常、開発はだんだんと要件が明確になっていきます。それに合わせて、テスト活動も継続的に行っていくことが大切です。

先ほどの会員登録の事例をもう一度考えてみます。例えば、開発の初期においては、以下のようなことしか決まってないかもしれません。

  • 「会員登録において、設定できるユーザー名が適切なものであるかをチェックする」

この時点では、「ユーザー名に何らかの制限を設ける」ことは決まっていますが、具体的な制限についてまだ定められていないのでしょう。このタイミングでテストを考えると、以下のようなものが出てきます

  • ユーザー名の文字数について確認する
  • ユーザー名の文字種について確認する
  • 適切でなかった場合の挙動について確認する

この時点では、例えば「文字数について確認する」ことは必要だと認識しましたが、具体的に何文字をテストすべきかを明確にしていません。

その後、プロダクトバックログアイテムのリファインメントを通じて、テストすべき内容を元に議論を行い、以下のように要件が定まってきたとします。

  • 「会員登録において、ユーザー名の文字数が4文字以上12文字以下になっているか、文字種が英数字のみであるかをチェックする」

これに合わせてテストすべき内容についてもアップデートを行います。

  • ユーザー名の文字数について確認する
    • 文字数が4文字、12文字のとき、有効であることを確認する
    • 文字数が3文字、13文字のとき、無効であることを確認する
  • ユーザー名の文字種について確認する
    • 入力したユーザー名の文字種が英数字のみであるとき、有効であることを確認する
    • 入力したユーザー名の文字種にひらがな、カタカナ、漢字が含まれているとき、無効であることを確認する
  • 適切でなかった場合の挙動について確認する

このように、要件の不確実性がまだ多い初期の段階からテストのことをザックリと考え、要件が定まるに対応して、テストすべき内容を段々と明らかに(詳細に)定めていくことが可能です。

これが、継続的にテスト活動を行っていく具体的な内容の例です。

まとめ ── テスト活動を早い段階で行おう

本記事では、DevOpsのループ図をもとに考案された「継続的テストモデル」を紹介しました。また、「シフトレフトなテスト活動とシフトライトなテスト活動」という概念も紹介しました。そして、最初に取り組みやすい「シフトレフトなテスト活動」について具体例を交えて紹介しました。

今回紹介したような内容を業務に取り入れ、ぜひ早い段階でのテスト活動を行い、不具合の混入を防ぐように心がけてみてください。

また今回は紹介できませんでしたが、「シフトライトなテスト活動」も行うことで、よりユーザーの要求を満たすような開発が可能です。本記事を読んで興味を持たれた方は、シフトライトの事例を私が過去に発表しておりますので、そちらを参考にしてください。

テストの完了をゴールにしない! ~仮説検証を繰り返し、開発・QA・ユーザーが交流しながら開発することで見えてくる理想の姿~

合わせて読みたい関連記事

編集:はてな編集部

*1:編集部注:スクラムガイドではリファインメントについて「説明・並び順・サイズなどの詳細を追加するための継続的な活動である」とも述べており、継続的テストの活動と同様にフェーズやイベントではなく、いつでも行ってよい活動の1つです。

風間裕也さんプロフィールカット
風間 裕也(かざま・ゆうや) @nihonbuson
電気通信大学大学院修士課程修了。ワークスアプリケーションズに入社後、学生時代から興味のあった品質やテストに関わるためQAチームへ異動。ビズリーチを経て2023年5月から10Xの品質所属部に所属し、現職。B-Testingを開設し、社内外問わず「どのようにテストを考えればよいか」を日々エンジニアに伝えている。
Blog: ブロッコリーのブログ