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

.logbook

学んだことを書き綴る、言わば航海日誌です。

ETロボコンにおけるモックの役割と作り方

C言語 ETロボコン

これは、ETロボコン Advent Calendar 2014 - Adventarの 13日目のエントリーです。

昨日はpulmaster2さんによる「リタイア宣言をしよう!」でした。リタイアすることのないまま走行を終えるのが理想的ですが、何が起こるかわからないのがロボコンなのでいろいろなケースを想定しておく必要がありますよね。

概要

今回の書く記事は前回の記事の続編となります。

C言語の関数をユニットテストする場合における、モックの役割と作り方を解説します。

テスト対象

ETロボコンでしばしば登場する実装に「方位の計算」があります。

方位を計算することで、

  • 走行体の位置を推定する(カーブを曲がり終えたか?といった判定をする)
  • 特定の方向へ旋回する

といったことが可能となります。

大体こんな感じの仕組みで計算しているはずです。

f:id:ylgbk:20141213171636p:plain

この「走行体の方位を計算する」という処理がC言語で実装されたと想定し、ユニットテストする方法を考えてみます。

テストの構成と内容

私の場合、PCUnitの環境を構築し、テスト対象を呼び出すドライバを作成します。

f:id:ylgbk:20141213172710p:plain

次にテストで確認する項目を考えてみます。とりあえずこんな感じでしょうか?

f:id:ylgbk:20141213173722p:plain

実際は「エンコーダ値が負になった場合」、「エンコーダ値の値が非常に大きくなった場合」などもテストしたいところですが、とりあえず上記3ケースとします。

これでテストできると思い、テストコードを書くのですが、行き詰まります。

「モータのエンコーダ値を取得する(nxtOsek)」が厄介です。

f:id:ylgbk:20141213174614p:plain

「スタブ」と書いていますが、要は「nxt_motor_get_count()」の偽物を作る必要がありそうということです。

モックの必要性

「モータのエンコーダ値を取得する」ですが、まだ他にもやるべきことがあります。

実際にユニットテストするとき、

  • 「走行体の方位を計算する」が「モータのエンコーダ値を取得する」を2回呼び出していること
  • 「モータのエンコーダ値を取得する」の引数は右モータのポート、左モータのポートを指定していること

を確認する必要があります。

f:id:ylgbk:20141213180324p:plain

これをちゃんと確認しないと、尻尾モータのエンコーダ値を誤って取得していたり、同じモータのポートを2回取得していたりというコーディングミスが残ってしまう可能性があります。

このように、テスト対象の下位モジュールとして、「呼び出し回数」や「呼び出し時のパラメータ」をチェックする実装を「モック」と呼びます。

モックを作ろう

nxtOsekのAPIを全てモックとして実装し直すのは時間がかかります。

が、PCUnitではモックを自動生成するためのRubyスクリプトが付属していますので、便利です。

pcunit_mock.rbの部分に使い方が記載されています。

nxtOsekのAPIを全てモック化しておけば、ユニットテストが捗りますね。

終わりに

と、いろいろ書いてみましたが、やはり実際のコードや動いている様子を見ないとわかりにくいですね(;´∀`)

というわけで機会があれば、私が作成したテスト環境を公開したいと思っています。