チーム開発の視点が変わる アジャイル開発の新常識 第7回 手段が目的になっていない? アジャイルなテスト自動化とは

アジャイル/DevOps

2021.11.25

  

*本コラムは、技術評論社「Software Design」2021年6月号に寄稿したコラムを掲載しています。

なぜアジャイルと言えばテスト自動化なのか

アジャイル開発の現場で、テストを自動化していないところはないと言い切れるほど、アジャイルとテストの自動化は切っても切り離せない関係と言えるでしょう。テストにかかわらず、自動化の価値は十分浸透し、アプリケーション開発のシーンだけではなく、インフラ構築や業務プロセスなどでも活用されています。
ただ、「自動化」のような、広く普及したIT系のキーワードは、一人歩きを始めて本当の目的を見失い、手段が目的化してしまうことがあります。DevOpsやクラウド、AI、ビッグデータといったキーワードを聞いて、苦い経験のある読者もいるのではないでしょうか。ツール導入や環境整備で満足し、狙っていた効果が出ないならまだしも、状況が悪化したという声もよく聞きます。
そのようなことのないように、まずは一度原則に立ち戻り、なぜアジャイル開発でテスト自動化が必要なのかを考えてみましょう。

継続的な検査と適応

アジャイル開発手法の中で最も普及しているスクラムにおいて、重要な概念である、「透明性」「検査」「適応」についておさらいをしましょう。スクラムガイドによると次のように定義されています注1

  • 透明性:創発的なプロセスや作業を、作業を実行する人とその作業を受け取る人に見えるようにすること
  • 検査:望ましくない変化や問題が生じていないかを検知するため、スクラムの作成物と合意されたゴールに向けた進捗状況を検査すること
  • 適応:プロセスのいずれかの側面が許容範囲を逸脱していたり、成果となるプロダクトが受け入れられなかったりしたときに、適用しているプロセスや製造している構成要素を調整すること

ユーザーに届けるプロダクトの価値を継続的に最大化させるために、「透明性」を保ったうえで、「検査」と「適応」を短い周期で繰り返すのがスクラムのしくみです。
このときにプロダクトに対する検査は、価値と品質の2つの観点で実施します。今回は、品質の検査の自動化を取り上げます。
継続的に検査をするということは、継続的にコストがかかるということでもあります。そして何の対処もしないと、開発スタートから時間が経過してプロダクトが拡大するほど検査にかかるコストがかさみ、アジリティ(機敏性)を低下させることになります。そうするとアジャイルの目的である価値の最大化を達成できなくなってしまうでしょう。
継続的な価値の最大化のために検査のコストを下げてアジリティの低下を防ぐこと、これがアジャイルにおける検査の自動化(=テスト自動化)の真の目的です。

自動化はいつ始めるのか

開発の途中からテストの自動化を始めた経験はありますか? 経験がある方は、さぞ苦労されたことでしょう。
自動化導入を阻む原因はいくつかあるでしょうが、その主要なものとして「プロダクトがテストしやすい形(=テスタビリティが高い状態)になっていない」ということが挙げられます。

テスタビリティとは

では、テスタビリティとはどのようなものなのでしょうか?James Bachはテスタビリティを表す指標を表1のように提示しています注2

テスタビリティの指標
表1 テスタビリティの指標

テスタビリティはいつから意識して、いつから向上させればよいのでしょうか。
たとえば、テスタビリティを意識せずに開発を始めてしばらく経ったプロダクトはどのような状態になっているでしょうか。表1の分解容易性、単純性、理解容易性を考慮していないと、変更を局所化するためのモジュール化がされていない密結合の状態になっており、開発者からコンポーネントの依存関係を把握することが難しい状態になっていることでしょう。
また、テスタビリティを高めるために構成を変更するとその変更により別の部分で問題が起き、それを解決したらまた別の部分で問題が生じるというキリのないイタチごっこに終始したり、実装したメンバーがすでにプロジェクトから去っていてどういう意図で実装されたかわからないコードを解析することになったり、テスタビリティ確保のための新たな開発をしなければならなかったりすることもあります。
テスタビリティが初期から考慮されていれば、このような問題は起こりにくいでしょう。それまでに実装された部分は自動テストで一定の品質が担保されているので、変更するたびにその変更の単体テストと既存の自動テストを実施すれば、この変更によりほかの部分が壊れてしまってもそれにすぐ気づくことができます。また、どういう意図で実装されたか一見わかりにくいコードがあってもテストコードを見ることで当たりをつけることができます。
このように、途中から自動化を導入すると膨大なコストがかかるので、プロジェクト初期からテスタビリティを考慮した設計と自動化を実施することが大切です。

どのテストを自動化するか

では、テストの自動化を始めようとしたとき、どのような優先順位で自動化に着手すれば良いでしょうか。

粒度の細かいテストから自動化する

テストの対象となるプロダクトの範囲の大きさを「粒度」とすると、粒度の細かいテストから自動化を始めるのがいいでしょう。粒度が細かいテストが先に自動化されることで、問題箇所の特定がしやすくなるからです。
粒度の細かいテストは粒度の粗いテストに包含されます。粒度の粗いテストで問題が起こると、結局はその問題箇所を特定するために粒度の細かいテストを実行する必要があります。
テストを粒度によって分けるとき、表2のように粒度の細かい順に単体テスト、機能テスト、E2Eテストと分類することが多いです。これをテストレベルと呼びます。

テストごとの粒度
表2 テストごとの粒度

有名なもので、Mike Cohnが提唱したテスト自動化ピラミッド注3というものがあります(図1)。下から単体テスト、機能テスト、E2Eテストの順に積み重なっています。より下の層のテストほど、自動化の導入コストが低く、高速かつ安定して動作し、影響範囲が狭いため壊れにくいので、投資対効果が高いとされています。
自動化の投資対効果を最大化するため、できるだけ粒度の細かいピラミッドの下の層からテストするようにしましょう。

テスト自動化ピラミッド
図1 テスト自動化ピラミッド

投資対効果を見積もってから自動化を進める

粒度が同程度のテストが複数ある場合は、投資対効果を見積もって優先順位を付けましょう。
効果を「自動化によるコスト削減効果」、投資を「自動化導入コスト」とすると、投資対効果は次のように表せます。

投資対効果=(手動テストのコスト−メンテナンスコスト)÷(自動化テストのコスト+メンテナンスコスト)

表3に、投資対効果の見積もりの例を記載します。これは、プロジェクトの開始から終了までに、テストケースが3回変更され、そのテストを100回実施しなければいけないという例です。1ケースあたりのコストの大きさや、実施回数は、プロダクトのテスタビリティやテスト自動化を開始するタイミングによって変動するでしょう。

投資対効果見積もりの例
表3 投資対効果見積もりの例

プロダクトオーナーにはどう説明するか

優先順位付けが済んだら、順位の高いものから着手していきましょう。
ただし、そこでプロダクトオーナー(以下PO)が「自動化? それ本当に必要なの?」「自動化しても新しい機能が増えるわけではないでしょ」と懐疑的な反応をすることがあります。
それはある意味当然かもしれません。単体テストや機能テストは、プロダクトが要求どおりに動作することを確認するためのものです。これはつまり「狩野モデル」注4で言うところの「当たり前品質」です。プロダクトとしては充足していて当たり前のことなのです。テストを自動化することによって、ないと不満だがあれば満足するような「一元的品質」が得られるわけでもありませんし、プロダクトの価値を高めるような「魅力品質」になるわけでもありません。ですからプロダクトの価値を高めることを考えているPOからすれば、テストの自動化は無駄な作業に見えるかもしれません。
しかし、テストを自動化することで、この「当たり前品質」のコストを下げることができます。その分リソースを「一元的品質」「魅力品質」の向上に費やせることをPOに説明しましょう。

とあるチームの自動化奮闘記

筆者の体験を元にした、ある架空のひよっこチームが自動化を進めていく話を見てみましょう。開発メンバーは開発者A、開発者B、開発者Cの3人からなる小規模なスクラムチームで、Webアプリケーションの開発をしています。

ベロシティ低下の要因とは

7回めのスプリントを終え、スプリントレビューを行っているチームは現在、レトロスペクティブを実施しています。挙げられた問題について議論しているようです(図2)。

レトロスペクティブで挙がった問題と改善策
図2 レトロスペクティブで挙がった問題と改善策

開発者A「チームもスクラムに慣れてきていて成熟してきた気がするけど、最近ベロシティが下がってきているんだよね」
開発者B「スプリントを重ねるごとに同じ画面でも機能が増えてテストケースが結構な数になってしまって、そこにコストがかかっていると思う。ブラウザを開いて値を入力して結果を確認するために画面キャプチャを撮って……」
開発者A「僕もそこが原因だと思う。細かいテストも含めてすべて実施しているけど、かなり時間がかかっちゃうんだよな」
開発者C「でも品質を落とすわけにもいかないし……やっぱ手動テストだと限界かもしれない。テストの自動化を進めてみてはどうだろう?最初はコストがかかるけど、まだまだスプリントは続くから長い目で見れば効果は大きいと思う」
開発者A「でも自動化ってどうやればいいんだろう?」
開発者B、C「そうなんだよね……」

テスト自動化に挑戦したいが、進め方に悩んでいるようです。

スクラムマスター「では、自動化をどう進めていくかの調査を次のスプリントでやってみたらどうかな?」
開発者A、B、C「そうしよう!」

テストのスコープ

このチームでは、今まではできあがった機能に対して手動でブラウザを開いてテストしていました。見た目の挙動からでは確認できない内部的な処理に対するテストはデバッガを使用したステップ実行や、変数をデバッグログに出力して確認していました。

開発者A「ブラウザテストを自動化してくれるツールがあるらしい。これを試してみようか」

調査結果を検証するためにまずは1テストケースを実際に自動化することにしました。試行錯誤しながらもなんとか自動化することはできましたが……

開発者A「ただ、このやり方で全部自動化するとなると相当なコストがかかりそうだな……」
開発者B「確かにこれは現実的ではない気がするね。みんなこんなに苦労してやっているのかな?」

そんな折、外部連携している機能を開発しているチームからバグ報告がありました。解析を行うと私たちのチームが作成した機能のバグであることがわかりました。幸いまだリリース前ですので大きな問題にはなりませんでした。

開発者A「テストケースが漏れているね」
開発者C「同じような機能もチェックしてみたけど、この観点は全体的に漏れているよ」
開発者B「またテストケースが増えるのか……」
◆ ◆ ◆
開発者A「僕たちは外部システムと連携してテストしてしまっているけど、これだとスコープが大き過ぎると思う。いろいろ調べたんだけど、テストにはいくつか段階があって、今回のバグは単体テストで摘出されるものだと思う。単体テストを自動化するにはxUnitというツールを使うのが一般的らしい」
開発者B「確かに今回のバグがどちらに原因があるのか切り分けするだけでも時間がかかってしまったし、僕たちのシステム内で閉じたテストで見つけるべきだったんだね。僕たちのシステムの中でも、さらに局所化したのが単体テストになるのか」
開発者A「テストピラミッドという考え方があって、自動化についても単体テストを重点的にやるべきらしい」
開発者C「実際ブラウザからのテスト自動化はコストがかかり過ぎて現実的じゃなかったし、よし、単体テストを自動化するところから始めよう!」

テスト自動化の優先順位

方向性が決まったのでPOにも交渉してバックログ化して、開発チーム全員でテスト自動化に取り組むことにしました。

開発者B「どこから自動化を始めようか」
開発者C「スクラムらしく優先順位を決めて自動化を進めたほうが良いのでは?」
開発者A「どうやって優先順位を決めればいいんだろう」
開発者B「ここは頻繁に回帰テスト注5がいるからここから始めたらいいんじゃない?」
◆ ◆ ◆
開発者B「テストスクリプトを書くのに1週間かかった。でも、テストの実施は楽になったよ」
開発者C「1週間か……。これってよく考えたら手動テストでもそんなに大変じゃないんじゃない? 逆に自動化するのは大変だけど」
開発者A「投資対効果は自動化のコストと手動実施でのコストの天秤を考えなきゃいけないのか。今回の自動化対象は実は投資対効果はそんなに高くないかもしれない。ほかにも考慮すべきパラメータはありそうだね」

テスト自動化が容易なアーキテクチャ

投資対効果を考慮した優先順位をもとにテスト自動化を進めています。

開発者B「ここをテストしたいんだけど、そのために準備することが多いなぁ」
開発者A「テスタビリティという考え方があるらしくて、僕たちのシステムはテスト自動化がしにくい構造になっている気がする」
開発者C「本当だ、このモジュールが密結合しているのが良くないのか。もっとモジュールを分けてテストしやすい単位に作り替えたほうがバグの調査をするときにわかりやすいと思う」
開発者A「まずはここをリファクタリングしてからテストスクリプトを書こう!」

エピローグ

手動でテストすべきところと自動化を進めるべきところの線引きも明確になり、テスト自動化はどんどん進んでいます。当初の課題だったベロシティについては、今では元どおりどころか1.5倍に上がっています。開発チームも自動化の効果を体感し、さらなる学習を進めて、テスト以外の自動化についても検討し始めているようです。
このチームはこれからも継続的に改善を進めていくことでしょう。

別の観点からテスト自動化を促進する

ここまでで、テストをいつからどうやって自動化していけばよいかを紹介してきましたが、本節では、別の観点からテストの自動化を促進する方法を紹介します。

ドキュメント整備

アジャイル開発宣言に「包括的なドキュメントよりも動くソフトウェアを」という記述があることから、アジャイル開発者の中にはすべての情報をソースコードのコメントとして記述する人もいるでしょう。しかし、これが行き過ぎてしまうと、自動化をプロダクトに広く導入したい場合に、障害になることがあります。情報がソースコードの中に偏在しているので一覧性がなく、プロダクト全体の仕様を理解するまでに多くの労力を要することがあるのです。このようなことを避けるためにも、アーキテクチャ全体を俯瞰的に記述したドキュメントを作成しておくことは価値があります。

継続性を確保するための教育

アジャイル開発では自動化も導入して終わりではなく、プロダクトの変更に追随し、継続的にメンテナンスし続ける必要があります。自動化が一部の開発者のみに委ねられていると、その開発者がなんらかの理由で自動化作業に従事できなくなったときに、メンテナンスが滞ってしまいます。これを防ぐためには、チームメンバーの大半、できれば全員が自動化手順を理解し、自律的に実施可能な状態であるのが望ましいです。メンバーへのスキルシェアのために、マニュアルなどの文章による伝達に加え、ペアプログラミングやモブプログラミングなども活用しましょう。

最後に

今回の記事では、アジャイル開発においてテストの自動化をどんな思想でどのように進めていけばよいか具体例を交えて紹介しました。
キーワードに踊らされて思考停止でテスト自動化を進めるのではなく、真の目的の達成のための手段の1つとしてテスト自動化がある、ということを忘れてはいけません。

アジャイルコラム記事一覧

https://www.intellilink.co.jp/column/agile-devops.aspx

※図は技術評論社の許諾を得て掲載しています。

  • 注1)https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf
  • 注2)J. Bach『Principles of Software Testability』の一部に対して、筆者が意訳を行ったものを表として掲載しています。
    https://groups.google.com/g/comp.software.testing/c/6J_pEufSzq8/m/LrbgESWNLdcJ?pli=1
  • 注3)Mi le Cohn, Succeeding with Agi le: SoftwareDevelopment Using Scrum, Addison-Wesley Pub. Co.,2009
  • 注4)顧客の求める品質をモデル化したもの。このモデルは東京理科大学名誉教授の狩野紀昭氏が提唱したもので、顧客の求める品質について、不充足でも不満はないが充足されれば満足な「魅力品質」、不充足だと不満で充足されると満足する「一元的品質」、不充足だと不満で充足されて当たり前の「当たり前品質」の3つに分けています。
  • 注5)プロダクトの変更によって、今まで正常に動作していたほかの部分が壊れていないか確認するテストのことです。プロダクトが変更されるたびに実施します。