これは、ETロボコン Advent Calendar 2014 - Adventarの 13日目のエントリーです。
昨日はpulmaster2さんによる「リタイア宣言をしよう!」でした。リタイアすることのないまま走行を終えるのが理想的ですが、何が起こるかわからないのがロボコンなのでいろいろなケースを想定しておく必要がありますよね。
概要
今回の書く記事は前回の記事の続編となります。
C言語の関数をユニットテストする場合における、モックの役割と作り方を解説します。
テスト対象
ETロボコンでしばしば登場する実装に「方位の計算」があります。
方位を計算することで、
- 走行体の位置を推定する(カーブを曲がり終えたか?といった判定をする)
- 特定の方向へ旋回する
といったことが可能となります。
大体こんな感じの仕組みで計算しているはずです。
この「走行体の方位を計算する」という処理がC言語で実装されたと想定し、ユニットテストする方法を考えてみます。
テストの構成と内容
私の場合、PCUnitの環境を構築し、テスト対象を呼び出すドライバを作成します。
次にテストで確認する項目を考えてみます。とりあえずこんな感じでしょうか?
実際は「エンコーダ値が負になった場合」、「エンコーダ値の値が非常に大きくなった場合」などもテストしたいところですが、とりあえず上記3ケースとします。
これでテストできると思い、テストコードを書くのですが、行き詰まります。
「モータのエンコーダ値を取得する(nxtOsek)」が厄介です。
「スタブ」と書いていますが、要は「nxt_motor_get_count()」の偽物を作る必要がありそうということです。
モックの必要性
「モータのエンコーダ値を取得する」ですが、まだ他にもやるべきことがあります。
実際にユニットテストするとき、
- 「走行体の方位を計算する」が「モータのエンコーダ値を取得する」を2回呼び出していること
- 「モータのエンコーダ値を取得する」の引数は右モータのポート、左モータのポートを指定していること
を確認する必要があります。
これをちゃんと確認しないと、尻尾モータのエンコーダ値を誤って取得していたり、同じモータのポートを2回取得していたりというコーディングミスが残ってしまう可能性があります。
このように、テスト対象の下位モジュールとして、「呼び出し回数」や「呼び出し時のパラメータ」をチェックする実装を「モック」と呼びます。
モックを作ろう
nxtOsekのAPIを全てモックとして実装し直すのは時間がかかります。
が、PCUnitではモックを自動生成するためのRubyスクリプトが付属していますので、便利です。
pcunit_mock.rbの部分に使い方が記載されています。
nxtOsekのAPIを全てモック化しておけば、ユニットテストが捗りますね。
終わりに
と、いろいろ書いてみましたが、やはり実際のコードや動いている様子を見ないとわかりにくいですね(;´∀`)
というわけで機会があれば、私が作成したテスト環境を公開したいと思っています。