本連載の主なテーマは、信頼できる実行結果にできるだけ短い時間でたどり着く自動テスト群の構築です。連載の区切りとして、なぜ自動テストを書いてメンテナンスしていくのか、そしてそれに立ちはだかる
自動テストを書く動機
自動テストを書く動機には、不具合混入を防止する、問題箇所の絞り込みを容易にする、動く仕様書やサンプルになるなどいろいろありますが、最大の動機は、変化を抱擁し、ソフトウェアの成長を持続可能なものにすることだと筆者は考えています。
ソフトウェアを取り巻く世界は変わりました。ソフトウェアは世界を飲み込み、事業と一体化しました。事業を取り巻く市場もエンドユーザーのニーズも刻々と変化する時代においては、より速く、より安全に変化する力が求められます。コードを変更しなければ動き続けることが期待できる時代ではもうなく、決められたものを決められたときまでに破綻なく作ればよい時代でもなくなりました。変えなくてよいソフトウェアを作るのではなく、欲しいときにすぐに望ましい形にできるような、変更しやすく、変化に対応できるソフトウェアが競争力になる時代に変わったのです。ソフトウェア開発は、事業が成長する限り完成も終わりもなくなり、継続的な変更と改善を続けるものになりました。
継続的な変更と改善を続けるうえで鍵となるソフトウェアの品質特性は
自動テストが整備されていれば、開発しているシステムが自分たちの想定どおりに動いていることが短い時間で確認でき、誰のコードでも同じように編集でき、動かなくなったらすぐにわかります。すると、いつでもどこからでも改善に着手できるという自信が生まれます。ソフトウェアを取り巻く環境の変化に合わせて迅速かつ安全に変化させていくための根拠ある自信こそが、自動テストの最大の効果だと筆者は考えています。
脆いテスト
では、世の中を見回してみるとどうでしょう。自動テスト、特に自動化されたユニットテストに関する意見や感想で、現在でもよく見かけるものがあります。
ソフトウェアを少し変化させるたびに大量のテストを変更しなければならない状況は
脆いテストが多いと、テスト対象の些細な変更であってもすぐにテストが失敗してしまうのでメンテナンスコストがかさみます。すると、自動テストの支えによって変化に対して前向きになるべきところが、テストのメンテナンスが面倒だから変化は面倒だ、やめておこうといったように、むしろ後ろ向きになってしまいます。これでは本末転倒です。
脆いテストの原因と対策
脆いテストの原因はテストコードとテスト対象との高すぎる構造的結合度です。構造的結合度とは、テストコードがテスト対象の構造、たとえば名前空間、クラス、メソッドや関数の名前や型などに依存している度合いです。もちろんテストコードにはある程度の構造的結合はありますが、テスト対象の内部構造やアルゴリズムといった実装の詳細に依存してしまうと、プロダクトコードの内部を少し変更しただけでもテストが失敗するようになってしまいます。
では、実装から遠いインテグレーションテストやE2E
脆いテストになりにくくする指針を3つ挙げます。
- ⓐ 公開API経由でテストする
- ⓑ 構造単位ではなく振る舞い単位でテストする
- ⓒ 相互作用ではなく事後状態をテストする
ⓐは、テストコードからはテスト対象の公開APIのみにアクセスし、公開されていない要素、たとえばプライベートフィールドやプライベートメソッドは直接扱わないようにするということです。公開されていない要素は、公開APIから見た振る舞いを変えない範囲で変更や改善を行われる可能性が常にあります。公開されていない要素を活用したテストが書かれてしまうと、そういった内部の改善を妨げる原因になってしまいます。
ⓑは、テストとテスト対象の構造を対応付けないということです。クラスやメソッド、関数をテストの数や構造と対応させるのではなく、振る舞いや責務に対してテストを対応付けます。テスト対象の1つの関数が3つの仕事を行う場合は3つのテストを書きます。責務をほとんど持たず、ほかのクラスのテストでカバーされているクラスにテストを書く必要はありません。
ⓒは、テスト対象内部のやりとりをテストしないということです。たとえば、テスト対象オブジェクトAがさらに別のオブジェクトBやCに依存している場合、AとB、Cとの相互作用、たとえばメソッド呼び出しの中身や回数をモックオブジェクトなどを活用してテストしたくなりますが、それは諸刃の剣になります。そういった相互作用のテストを書けば書くほど、些細な内部設計の変更に対してもモックを追随させる必要があり、変更コストが上がっていきます。テストでは外部から観た振る舞い、たとえばテスト対象のメソッドの戻り値や、テスト対象のメソッド実行後の事後状態を検証しましょう。
おわりに
構造的結合に注意し、継続的な変更と改善を支えるテストを書きましょう。本連載はここで一区切りです。みなさま、誠にありがとうございました。