Test-Driven Development for Embedded C 第5章

Test-Driven Development for Embedded C の5章を読んだので簡単にまとめや感想を書いていこうと思う。


5章のタイトルは"Embedded TDD Strategy" 訳すと「組み込みTDD戦略」。組み込みならではのTDDのやり方が学べそう。

4章でLEDドライバのTDD実践をやったらしい(まだ読んでない)が、これはホスト環境(PC等の開発環境)でテストしたもの。ホスト環境ではテストパスしたけど、ターゲット上で動かしてないのにテストしたっていえるのか?

しかし大抵の場合、組み込みソフトウェアの開発を始めるときにターゲットハードウェアが既に用意されていることはまずない。あったとしても、用意できるターゲットの数は限られるし、ハード自身のバグもある。

だから、この章ではDual-Targettingでテストすることを考えよう、と書いている。
Dual-Targettingとは、ホスト環境とターゲット環境の両方でテスト可能なコードを書こうというもの。

最初にホスト環境でTDDすることによって、ハードが来るまでソフトのテストができないという状況を防ぐ。ハードが来て初めてソフトのデバッグをしていては遅いのだ。いざハードが用意できて、ターゲット上でそのユニットテストを動かしてみてテストに失敗→これはハードのバグかソフトのバグか?の判断がしやすくなるというメリットもあるらしい。
さらに、なるべく両方の環境で動作するように考えることで、ハードウェア依存やOS・ライブラリ依存の部分をできるだけ局所化して移植性の高い設計にする狙いもありそうだ。

Dual-Targettingのリスクとしては、やはりホストとターゲットのコンパイラや使えるシステムコール・ライブラリが違うなど。また、データ型のサイズやバイトオーダー(ビッグエンディアン/リトルエンディアン)や使えるメモリ量やスタックサイズなども考慮する必要がある。この辺りはなるべくターゲットに合わせて考えるのがいいのかな。システムコールなんかは一度ラッパーとかスタブを作れば使いまわせるかもしれない。


組み込みTDDのサイクルとして、とてもわかりやすい図があったので引用してみる。

  • ステージ1は普通のTDDと同じでホスト環境上で、頻繁にユニットテストを繰り返す。
  • ステージ2はターゲット用のクロスコンパイルをしてみる。
  • ステージ3は評価ボードやエミュレータ上でユニットテストする。
  • ステージ4は実際のターゲットボード上でユニットテストする。
  • ステージ5は受け入れテスト。自動テストだけでなく、手動のテストも行う。

ステージが進むにつれて実行回数が減っているのがわかる。ターゲット上で動かすということはプログラムをターゲットにダウンロードしたりCF書き換えたりとそれなりに手間がかかるので、ステージ1の段階でテスト→リファクタリングを繰り返しておくようだ。ステージ1ではコードのハードウェア依存の部分を切り離しておく。ハードウェア依存の部分にはスタブを使うということだろう。
ステージ2ではクロスコンパイルすることでホスト環境とターゲット環境のコンパイラの違い、ヘッダファイルやライブラリなどの違いを修正する。
ステージ3。評価ボード上でユニットテストをすることで、ホスト環境とターゲット環境で実際にどう違うのかがわかる。組み込み向けのランタイムライブラリにもバグがあるかもしれないから気をつけましょうと書いてある。このステージではどうやってプログラムを実行させるのかは書いてない。おそらく評価ボードにはJTAGデバッグ用シリアルポートが用意されているので、そこからダウンロードしてテストを実行させるやり方だろう。CI(Continuous Integration)を使って少なくとも毎日ビルドとテスト実行をやるべきと書いてるが、HEWなどのIDEを使ってる場合、自動でできるのだろうか?
ステージ4。実際のターゲットでユニットテストすることで、ハードウェア仕様のテストも兼ねてるらしい。ということは、ハードのレジスタにアクセスする部分は、スタブから実際のハードに切り替えなきゃいけないだろう。また、メモリに制限がある場合は、メモリ内に収まるように適宜テストを分割して別々で実行しなければならないようだ。実際のターゲットだとJTAGも使えないだろうから、いちいちFlashROMに焼いたりCF挿し替えたりしなければならないかも。少々めんどうだ。
ステージ5は、自動でできないテストを手動でやる。TDDでなくてもいつもやってることだ。
これらのステージはすべて行わなければならないというわけではない。ステージ3と4はそれほど分ける必要はないのではと思った。


この章のポイントは

  • Dual-Targettingでホスト・ターゲット両方でユニットテストをやるということ。
  • ターゲット上でユニットテストを動かすということはハードのテストも兼ねているということ。

組み込み開発ではハードのバグもよくあることだが、真っ先にソフトのバグが疑われる。組み込みプログラマーはハードのバグである証明をしなきゃいけない。だからハードのバグかソフトのバグかの判断をするための手段としても、組み込みTDDが使えると思った。