単体テスト導入のメリット
このチャプターは一般的な単体テスト導入によるメリットの説明です。すでに単体テストに詳しい人は読む必要はありません。早く組み込みで単体テスト導入する方法を知りたいという人は次の章に進んでください。
メリット
工数削減
モノを動かすためのコード(プロダクトコード)に プラスしてそれをテストするためのコード(テストコード)を書く必要があるため工数が増えると考える人もいます。たしかに開発の初期段階ではテストを書かないほう早く進められるでしょう。しかし、ある程度の規模になると単体テストを導入しているほうがトータルコストは下がっていきます。
実行時間が短くすぐさまフィードバックを得られ、仕様変更の影響を受けずらい単体テストは統合テスト、マニュアルテスト(E2Eテスト)よりもリターンを得やすいです。規模の小さいプロジェクトでも導入する価値はあるはずです。使い捨てのスクリプトとかでない限りテストにかかる工数はペイできます。
デグレの防止
多数の設定値、バージョンの組み合わせ等をすべて考慮して機能を追加するのは難易度が高く、動作確認にコストがかかります。次第に「このテストケースは今回の変更とは関係ないよね」といった感じで一部の動作確認をスキップするようになっていきます。しかし実際には、変更が本当に影響を与えないかどうかを完璧に予測することは誰にもできません。
自動テストならば実行のコストはほぼ0です。commitごと、pull requestごとといった風にソースコードに変更を加える度に自動テストを走 らせることでデグレが発生していないことを素早く検証できます。
バグ発生箇所を特定
単体テストで失敗してもテスティングフレームワークがどこで失敗したか、期待値は何で実際の値は何かを示してくれます。マニュアルテストでバグを見つけ出そうと思ったら実際にモノを動かして時間をかけてバグを出して、そこから問題の部分を特定する作業が発生します。
自信を持って開発を進める
新しくコードを追加して、既存のテストがこけたなら、新しく書いたコードの中に問題がある。テストが通れば安心。
シフトレフト
マニュアルテストしかなければ現物ができるまでソフトの動作を確認することができません。もし基板の完成が遅れたりデバイスの数が限られていたら開発を進めることができません。単体テストがあればPC上でコンポーネント単位ではありますが、検証が可能です。
これにより開 発工数を開発プロセスの前半に持ってくることが可能です。開発段階が後ろにいくほど同じ修正でもコストは上がるため、シフトレフトにより工数の削減が期待できます。
動く仕様書
googletestのテストケース実行用マクロTEST
は引数にテストケース名を入れます。これによりテスト対象のコードのふるまいを説明することができます。TEST(テストスイート名, テストケース名)
(日本語も入れることができます)
TEST(Counter, オーバーフローしても正しく経過カウントを計算できる) {
uint32_t startValue = 0xffffffff;
uint32_t currentValue = 0x9;
EXPECT_EQ(10, Counter_GetElapsedCount(startValue, currentValue));
}
Doxygenのようなツールで関数の説明をしても良いですが、実装と関数の説明が一致している保証はありません。
/**
* @brief 経過カウントを計算する
*
* オーバーフローしても正しく経過カウントを計算できる
*
* @param startValue 開始カウント
* @param currentValue 現在のカウント
* @return 経過カウント
*/
uint32_t Counter_GetElapsedCount(uint32_t startValue, uint32_t currentValue) {
return currentValue - startValue;
}
関数の仕様変更や改修が重なれば説明を編集し忘れた、ということも出てくるでしょう。仕様に変更がありプロダクトコードに変更があったとき、もしテストコードの修正を忘れていてもテスト実行時にエラーが出るため気づくことができます。
エッジケースを検証する
オーバーフローした時とか、うるう年とか、SDカードがいっぱいになった時のようなマニュアルテストでは検証が難しいケースでもふるまいを検証できます
単体テストの懸念
テストを導入した後は、プロダクトコードと同様にテストコードも管理していく必要があります。仕様が変更されれば、プロダクトコードだけでなく、テストコードも変更する必要があります。
「ほら、単体テストなんて意味ないし、定着しないよ」という声が聞こえることもあるかもしれませんが、私は単体テストが使えないとは思いません。実際、さまざまなソフトウェア開発に関する書籍では、単体テストに1章以上割かれていることが多く、それだけ重要視されている分野です。そうした文献を目にしてもなお、単体テストを無意味だと言うのは、少々勇気がいるのではないでしょうか。
むしろ、単体テストが定着しないのは、ソフトウェア設計やテストコードの管理に関するスキルをまだ習得できていないからかもしれません。テスト可能で、仕様変更にも強いソフトウェアを作るには、ただ動作するだけのソフトを作るよりも高いスキルが必要です。