読者です 読者をやめる 読者になる 読者になる

組込みでのテストファーストの導入について

 現状として、自分の裁量内では部分的にテストファーストの導入ができていると思う。
 テストファーストに関しては、一部でトリッキーな印象を持たれているようだけれど、やってみる限り、そんなに違和感のあるものでも、難しいものでもないと感じる。

 例えば自分は主にCやverilogといったレガシーな言語を使っているけれど、そういった言語ではカプセル化やスコープの制限を支える言語機能が貧弱なので、使っているとモジュールのインターフェースを慎重に考えるようになる。その「モジュールのインターフェースを慎重に考える」というステップが、思えばEDDやBDDのアプローチと同じで、テストファーストと親和性が高いように感じる。


 なおテストファーストの効果は結構感じている。具体的なメリットは色々あるが、特に大きいのが以下の4つ。

コードがテスト可能になる

 テストを実行できるスケルトンを実装していくわけだから、自ずとコードがテストしやすい形を取るようになる。これは後からリファクタリングや機能変更を実施するのをかなり楽にする。

仕様記述に近いテストが得られる

 読書会で翻訳しているxUnit Test Patternsでも触れられていたけれど、実装されていない状態で考えるテストは、自然と用例を示すような形を取る。この用例としてのテストはまさに「テストコードがドキュメント」を体現したようなもので、開発者向けの覚書として有効に機能している。

インターフェース設計が洗練される

 実装に入る前にモジュールの用例やふるまいを想像するステップを入れると、(構造化設計でいう)インターフェースをより深く評価できるように感じる。これはインターフェースの設計の間違いを防止するのに有効で、モジュールの流用や共同開発を円滑なものにする。

仕様・アーキテクチャが検証される

 コードがない状態でテストを考えようとすると、まずテストベースである仕様やアーキテクチャをブレークダウンする必要がある。そのブレークダウンするステップで、仕様やアーキテクチャの改善点が結構あぶり出されるようになっている。またその過程で、仕様やアーキテクチャと無関係な冗長なコードも減ると感じる。


 ただ注意として、以下のような問題も感じている。

テストの自動化が限定的

 組み込みだからだと思うけれど、自分のところではテストファーストのテストを完全に自動化できていない。特定モジュールを抜き出して自動化している状況。TDDの適用も周りと比べれば割合は大きい方だとは思うが、限定的なものになっている。

書かれるテストが部分的

 テストファーストでかかれるテストは、ユニットテストとしては不足の多い、かなり断片的な網羅度になる。逆にテストファーストで十分な網羅度のテストを設計しようとすると、テストの漏れが出たり、テストの修正が後から必要になったりして、かえって開発効率を落とすように感じる。そのためテストファーストのテストはモジュールの実装の方向性を示す程度、あるいはモジュールのテスト容易性を確保する程度の手段として扱っている。テストファーストはそのままでも効果的だが、テストファーストで得られるテストを効果的に運用するには、別のプロセスの支援が必要になると思う。


 1番目に関してだけれども、TDDにこだわらないというアプローチが、組み込みでは必要だと感じている(ただこれは環境の制約も大きいかもしれない)。というのも「テストファーストではあくまで大まかなモジュールの妥当性テストをやるだけ」と見なせば、Embedded Unitみたいにテスティングフレームワークごとマイコンのイメージファイルにしてしまう方法が許容され、単体テスト可能なコードが大きく増えるからだ。ただこれに関しては一部で問題を感じているのでもう少し勉強を進めてみようと思う。

 なお実際に実践しているとすぐに分かることだけれど、仕様を考えるといってもテストファーストとシステムテスト設計は大分違う。というのも、仕様分析で仕様のトレーサビリティを維持しようとするシステムテスト設計で必須の作業が、テストファーストでは省略可能だからだ。例えばテストファーストでは上流仕様を考えずに実装イメージ重視でテストを書いていくことが可能だ。そのためシステムテストからテストファースト向けのテストを作ることはできても、その逆をやるには色々注意が必要になってくると感じる。