■
こちらの講演時にいただいた質問への回答です。
「テスト自動化とテスト駆動開発」講演資料 - やっとむでぽん
質問1. テスト駆動開発した結果のテストコードは、最終的にテスト自動化に寄与しますか?
はい、テストコード自体は寄与しないことも多いですが、テスト駆動開発自体はテスト自動化に寄与します。
テスト自動化にあとから取り組むとき、最大のネックは「テストが書けない」ことです。これはテストを差し込んだり、テスト対象を独立して取り出したりするのが、依存関係のせいでできない状態です。典型的には、1つの処理が何百行にも渡っていて、一部だけをテストできない。1クラスのロジックをテストしたいのに、他のクラスやデータベース、ファイルやシステム間通信まで必要になって、対象だけを取り出せない。
これらは設計の問題ですが、テストを書こうと思わなければ特に問題にならない場合もあります。(もっと言うと、変更しようと思わなければ問題はない。) そのため、後になってからテストを書こうとすると、設計変更が必要になってしまい、よけいに手間がかかります。
テスト駆動開発を導入していると、個々のクラス、個々のロジックについてテストを書いているので、自動的にテストが書ける設計になります。こうなっていると、テストを書き足すのは簡単です。また、設計を評価する一般的な指標である、高凝集・低結合や、単一責任原則、抽象への依存などにも近づきやすくなります(これは自動的にというよりは、意識しやすくなるという感じです)。そういう意味で、テスト自動化をやりやすい状態が実現できます。
上記の議論は、ほぼユニットテスト(コンポーネントテスト)の話になります。テスト自動化はそれ以外の、統合テストやシステムテストも対象になりますが、こうしたテストについては、テスト駆動開発はあまり関係ないと思います。BDDなど、近いけれど別のアプローチが有用かもしれません。
テスト駆動開発で書いたテストコード自体は、テストの整理(テストのリファクタリング)で整理統合されたり、品質観点のテストを書く中で吸収されてしまったりすることも多く、テスト駆動開発でテストをたくさん書いたから自動化は早く終わる、というふうにはいかないと思います。
質問2. リファクタリングはかなりの高技術だと思います。今回はそこには触れないのでしょうか?
リファクタリングについて、今回の講演では主にその効果の話だけをして、具体的なやり方には触れませんでした。それは実際のコードに触れながらでないと、理解が難しいと思います。和田卓人さんによるテスト駆動開発の講演とライブコーディングの動画が、リファクタリングの実際についても基本がわかるので、おすすめです。
ここでリファクタリングについて、もう少し詳細な話を補足します。リファクタリングという言葉は、3つくらいの側面があります。
- 技法としてのリファクタリング、「リファクタリング」という名詞 ― コードの動作(機能)を変えずに構造を変えて、読みやすくしたり、変更しやすくする一連のテクニック。ほんの数行を変える程度の、小さな規模のものが主。1つ1つはシンプルだが、種類が多い。
- プロセスとしてのリファクタリング、「リファクタリングする」という動詞 ― 一連のリファクタリング(A)を適用して、ソフトウェアの機能を変えずに維持したまま、再構築すること。数時間以上かかることもある。テスト駆動開発のサイクルでは毎回「リファクタリングして」ソフトウェアを直し続ける。
- 取り組みとしてのリファクタリング ― 問題意識を持って、ソフトウェアの一部についてきれいに作り直すべく、仕事として取り組む活動。数日から数ヶ月かかることもある。
Aは技法としては簡単ですし、ツール(IDE)が自動実行できるものもあり、誰でもできるようになります。ただしAのリファクタリングには「方向性」がありません。X→Yというリファクタリングも、X→Zというリファクタリングも、Y→Xというリファクタリングもあります。XとYとZのどちらがよりきれいなのかは、リファクタリングを越えた設計論が必要になります。どう命名すれば読みやすくなるか? 長くても読みやすい方がいいのか、短い方がいいのか? 似た処理を共通化した方がいいのか、意味が違うからと別にしておいたほうがいいのか? このメソッドはpublicかprivateか?
Bのリファクタリングは、設計論を知った上で「こういうふうにしたらきれいだろう」という方向性を持ち、そちらに向けてAのリファクタリングを積み重ねる作業になります。そのためには設計論を知っていたり、チームとして合意している必要もあります。
Cは大規模な設計改善です。ひとつのプロジェクトと考えられます。計画もあるし、改善後の設計イメージをあるていど固めてから実施します。
このように考えていくと、リファクタリングというのは確かに高度な技術です。これはしかし、リファクタリングそのものが高度なのではなく、作っているソフトウェアをきれいに直すために高度な技術が必要だと考えることもできます。リファクタリングは、その技術をちゃんと適用していく時間だと言えます。