更新 2024.03.08
テスト駆動開発(TDD)は、ソフトウェア開発の“やり方”の一つで、その名の通り、テストが開発を牽引する方式です。 しかし、初めて聞く方や、なんとなく理解しているだけの方にとっては、具体的な内容やそのメリット、実践方法がわかりづらいかもしれません。この記事では、テスト駆動開発とは何か、なぜそれに取り組むのか、そしてどのように始めれば良いのかについて詳しく解説します。 また、テスト駆動開発についての誤解や勘違いを解きほぐすための情報も提供します。 テスト駆動開発は、一見すると長い道のりに見えるかもしれませんが、実際には一歩一歩進めば容易に始めることができます。この記事を通じて、テスト駆動開発の理解を深め、その取り組みを始める一歩を踏み出してみてください。
テスト駆動開発とは|TDDとは何か
テスト駆動開発は、プログラミング手法、コードを書き進めるやり方です。プログラマーが安全にかつ素早くコードを書き進めていくための手法であり、各種テスティングフレームワークを利用します(JUnit、Jest、pytest、RSpecなど)。テスト駆動開発はTest-Driven Developmentの訳語で、よくTDDと略して表記されます。
TDDを実践するプログラマーはプロダクトコードを書く際に、自動化したテスト(テストコード)も並行して書いて、プロダクトコードの動作を確認しつつ作業を進めます。そのため、ありがちなプログラミングエラーを避けやすくなります。書いたプロダクトコードが思った通りに動作するか確認するので、後から実行したときにエラーが出たり、本来の仕様と違う結果が出たりは、あまりしません。それに加え、読みやすく変更しやすいコードになっているか同時に確認するため、わかりにくくて後から直すのが大変なコードを残すような事態も、あまり起きなくなるのです。
TDDは手順として、以下のサイクルを繰り返します。サイクルには6つのステップがありますが、全ステップを数分~10数分くらいのごく短い時間で終わらせてまた1.から始めます。動くコードを書き、書いたコードをきれいにするという、小さな変更を積み重ね、丁寧に育てていくようにコードを書き進めます。
テスト駆動開発のサイクル
1. 次の目標を考える
2. その目標を示すテストを書く
3. そのテストを実行して失敗させる (RED)
4. 目的のコードを書く
5. 2で書いたテストを成功させる (Green)
6. テストが通るままでリファクタリングを行う (Refactor)
7. 1~6を繰り返す
引用:見てわかるテスト駆動開発 / TDD Live and Workshop 2019 P12 より Spring
名前の印象とは違い、テスト駆動開発はテスト手法ではありません。TDDは従来のテストを不要にする魔法のテクニックではありませんし、プログラマーが突然、抜けや漏れのない必要十分なテストを設計できるようになるはずがないのです。TDDをしていると明らかにバグの量は減りますが、TDDだけで品質保証テストの替わりにはなりません。
テスト手法ではないとは言え、TDDはテスト技術者の仕事にも関わります。TDDで開発したコードでは単純なバグが減るので、テスト技術者はより見つけにくいバグの発見に集中できます。またテストの自動化を推進する上で、TDDは入り口になります。
テスト駆動開発のメリットとデメリット
テスト駆動開発の客観的なメリットデメリットとして、研究論文を紹介しているこちらのスライドを引用します。
TDD導入効果 (MS, IBM)
IBM Driver | MS Windows | MS MSN | MS Visual Studio | |
ソースコードサイズ (KLOC) | 41 | 6 | 26 | 155.2 |
テストコードサイズ (KLOC) | 28.5 | 4 | 23.2 | 60.3 |
TDDを採用していない類似プロジェクトでの欠陥密度を1とした時の欠陥密度 | 0.61 | 0.38 | 0.24 | 0.09 |
TDD採用により増加したコード実装時間(管理者の見積による) | 15~20% | 25~35% | 15% | 20~25% |
TDD導入効果(エリクソン他)
TDDを実施した場合に報告されている知見
・機能テストでの不具合検出数が18%削減された
・コーディング(実装)の時間が16%増えた
・テストのカバレッジが大きくなった
被験者を対象としたアンケート
・96%の被験者がデバッグの工数を減らすと感じた
・88%の被験者が要求が洗練されると感じた
・92%の被験者がコードの品質を上げると感じた
・50%の被験者が開発工数を減らすと感じた
引用:組織にテストを書く文化を根付かせる戦略と戦術(2020秋版) P42より
簡単にまとめると、TDDのメリット・デメリットは以下のようになります。
メリット
・欠陥が減る
・コードの品質が上がる
・デバッグ工数が減る
デメリット
・コーディング時間が増える
ここからは、単純なメリット・デメリットにとらわれない、TDDの効果について見ていきましょう。
テスト駆動開発に取り組む理由
テスト駆動開発に取り組む理由は、ズバリ「よりよいコードを書くため」です。意図した通りに動作するコード、理解しやすいコード、安全に追加変更できるコード、そうしたコードを、いまよりも上手に書けるようになる開発手法が、テスト駆動開発です。
よりよいコードの解釈は人や環境によって異なりますし、「よい」というのも曖昧です。ここでは書籍『リーダブルコード』から以下の定義を借りて説明しましょう。
鍵となる考え
『コードは他の人が最短時間で理解できるように書かなければいけない。』
「リーダブルコード」Dustin Boswell, Trevor Foucher, 角征典
仕様の素早い理解
後でコードを理解する他の人は、コードがどのような仕様を満たすのか、テストコードを見ればわかります。TDDではそのような、仕様をコードに写し取ったものをテストコードとして残します。他の人がコードを理解するには、まずテストコードから読めば仕様がわかるのです。
仕様はドキュメントでも理解できますが、ドキュメントが更新されていなかったり間違っていたりして混乱する場合もあります。テストコードであれば実態とずれても動かせばすぐわかるので、正しさが保証されます。テストコードは動作する仕様ドキュメントなのです。
理解しやすくするための時間確保
TDDのサイクルではリファクタリングを必ずおこないます。リファクタリングは、書いたコードが理解しやすいか見直して、より理解しやすいように変更する作業です。「あとで直します」ではなく、いま必ずやる。それがTDDで実現できます。
追加変更の時間短縮
動いているコードの機能を追加したり変更したりするには、まずコードを理解する必要があります。理解しやすいコードであれば、直接の結果として作業全体の時間が短くなります。さらに、正しい動作を確認するためのテストコードがあるので、変更漏れや思わぬ副作用にも、すぐに気がつけるようになります。より安全に、安心して作業ができるため、再確認や見直しの手間や、見落としを後で対処する時間も節約できるのです。
コードの理解は、実は他の人だけの問題ではありません。自分が書いたコードであっても、時間が経てば細かい点を忘れがちです。理解しやすいコードは、少し未来の自分自身のためになります。
つまりスピードが上がる
開発がアジャイルであってもなくても、既存のコードへの追加変更はつきものです。TDDにより追加変更が短期間でできるようになれば、すなわち開発スピードそのものが向上することになります。これはリードタイムの短縮、リリース頻度の向上という形で現れます。
ただし、これはTDDの直接のメリットではありません。TDDを導入し理解しやすいコードを書く習慣と文化が組織に根付き、手元にあるコードが実際に理解しやすいものばかりになってきて初めて、得られる結果です。
目に見える結果が出るまでには、時間も労力もかかります。すなわちTDDはたちどころに結果の出る魔法のツールというわけではなく、計画的に進める投資と考えるほうが適切です。
ひとりでも始められる
ところがTDDは、自分ひとりだけで小さく始めてもすぐに効果が実感できるという嬉しい側面もあります。自分が書くコードを、自分だけでTDDしながらテストを書きコードを理解しやすくしていけば、その部分だけでも今後の作業が楽に、安全になり、不安を減らせます。プロダクト全体をきれいにするのは大変ですが、今日、自分がさわる部分だけでも、安心してさわれるきれいなコードに直していけるのです。
テスト駆動開発のよくある勘違い
テスト駆動開発について、よくある間違い、勘違いもあります。TDDのデメリットにつながる話もありますが、誤解である場合もあります。
誤解:TDDは品質保証のためのテスト手法である
繰り返しになりますが、テスト駆動開発は名前の通り開発手法、プログラミングのやり方です。品質保証観点のテストは、別途必要になると考えてください。
とはいえ、プログラマーは書いたコードを必ずテストしているわけなので、単純なバグは減る傾向にあります。テストとしては不十分であっても、結果として品質が向上するという嬉しい副作用はよく見られます。
誤解:TDDは時間がかかる
これまでテストコードを書いていないのであれば、テストコードを書くぶん作業量が増える。これは間違いありません。作業をコーディングフェーズ、テストフェーズと切り分けると、コーディングの時間は増える傾向にあります。特にTDD導入初期は、慣れの問題もありコーディングに時間がかかります。
しかしその増加時間は、多くの場合テストフェーズの期間短縮で相殺されます。テストフェーズでは、テスト作業よりもバグの発見と修正に多くの時間が取られます。コードが理解しやすく、追加変更の作業が安全で、しかもテストコードで動作確認しているので、テストフェーズで発見されるバグの総量が減るのです。TDDのメリットとして「デバッグ工数が減る」という項目がありましたが、まさにここで効果を発揮します。
誤解:TDDはアジャイルのものである
TDDはプログラミング手法であり、よりよいコードが書けて、バグが減る傾向があります。これはどんな開発現場であってもありがたい話です。伝統的なウォーターフォールプロセスの現場でも、開発フェーズでTDDを活用できます。
TDDはアジャイルなソフトウェア開発として生まれ育ってきました。そのためXPであったり、スクラムであったり、アジャイルな開発でしかTDDは使わないと思われている場合があるようです。筆者は20年近く前、プロセスが厳密な銀行系のプロジェクトで、プロジェクトマネージャーと相談してTDDを導入し、生産性を向上させたことがあります。現代であればどんな現場でも使いどころがあると思います。
テスト駆動開発をはじめるには
ここまでTDDの効果や影響について説明してきました。興味が出てきた、詳しく知りたい、やってみたいという方のために、アプローチ方法をいくつかご紹介します。
プログラマーとしてTDDをはじめるには
自分自身がプログラマーとしてコードを書いている方は、なによりもTDDで実際にコードを書くのがオススメです。素晴らしい入門書として、ケント・ベック著『テスト駆動開発』があります。この本では、TDDでコードを書き進める様子をステップバイステップで、自分の手でコードを書き写しながら体験できます。よく「写経」と呼ばれる学習法です。著者はエクストリームプログラミング(XP)を作った人ですし、翻訳した和田卓人さんは業界をリードするエンジニアの1人です。和田さんが書き下ろしている解説も見逃せません。
■テスト駆動開発 Kent Beck, 和田卓人
https://shop.ohmsha.co.jp/shopdetail/000000004967/
実際に仕事で使えるようになるには練習も欠かせません。TDDに向く練習問題や、すぐTDDを試せる開発環境を試してみましょう。1人でやるのが難しければ、勉強会やコミュニティイベントに参加して教わったり相談したりしながら手を動かすのが効果的です。
■練習問題
https://nihonbuson.hatenadiary.jp/entry/2021/08/16/090000
■TDDを練習できる開発環境
https://cyber-dojo.org/creator/home
■勉強会やイベント
・TDDBC (TDD Boot Camp)
https://tddbc.connpass.com/
・TDDワイワイ会
https://tddyyx.github.io/
・テスト駆動飲み会
https://tddrinking.connpass.com/
テスト技術者としてTDDをはじめるには
プログラマーではなくテスターやテストエンジニア、SET(Software Engineer in Test)の方にもTDDは役に立ちます。テストの仕事に役立つ場合もあれば、テスト技術者としての知識や経験をTDDを通じて役立てられる場合もあります。TDDを実践しているチームがあれば、ぜひ様子を聞いたり、参加させてもらったりしましょう。モブプログラミングをしているところであれば、参加して様子を見るのに最適です。
テスト自動化エンジニアとしてテストコードを書いているのであれば、いちどプログラマーと同じアプローチで自分の手で書籍や練習問題でTDDを実践してみてください。開発手法としてのTDDは、自分で体験しないとなかなかイメージが掴みにくいです。
TDDで作ったテストを、テスト技術者の目で評価して傾向を知ったり、不足を見つけるのも、TDDを知る一助になります。プログラマーと一緒に、ペアプログラミングやモブプログラミングの形式で、レビューしたりテスト観点が明らかになるようテストコードを整理するのもいいでしょう。
チームや組織としてTDDをはじめるには
チームや組織としてTDDに取り組むのであれば、まずはメンバー個々人がTDDを学ぶよう働きかけましょう。それと同時に、仕事のやり方、進め方、プロセスとしてTDDを受け入れる準備も必要になります。
TDDはしょせん開発手法ですが、しかし開発手法が変われば、品質に関わる手法やプロセスが影響を受けます。TDD導入によって品質保証にどんな影響が出るか、むしろどうTDDを利用すれば良い効果が得られるのか、プロダクトと組織全体の視野で考える必要があります。そしてTDD導入をゴールとするのではなく、目指したい有り様をゴールとして設定します。4つの指標(Four Keys)を使うのもよいでしょう。コードの内部品質や、テスト技法や自動化のスキル獲得などの指標もいいかもしれません。
4つの指標(Four Keys)
https://cloud.google.com/blog/ja/products/gcp/using-the-four-keys-to-measure-your-devops-performance
品質保証の部門や担当者とTDDについて対話し、全体としてどんな効果が得られそうか、どんな影響があるか、ルールやプロセスをどう変えるか検討しましょう。CI/CDの導入や強化も必要になるかもしれません。
テスト駆動開発は長い道のりだが一歩はすぐに踏み出せる
テスト駆動開発によってよりよいコードを書くのは、プログラマーなら今すぐひとりでも始められます。続けていると、自分にとっての効果も実感できるでしょう。うまくいけば範囲を大きくしたり、同僚やチームに広めたりしながら、徐々に時間をかけ、大きな違いを生み出すこともできます。
テスト技術者にとっては、TDDは開発者とテストを結びつける接点になります。テスト嫌いな開発者でも、TDDを入り口としてテスト自動化や品質保証テストへの理解を深めてもらえるかもしれません。もしかしたら、テスト設計の知識経験を生かして、TDDの効果を高める手伝いもできるかもしれません。
テスト駆動開発でよりよいコード、そしてよりよいプロダクトへの道を歩んでみませんか?