2010年4月11日日曜日

Pythonコードをunittestでテストする

たまにはまじめにコードを書こうと思い、テストの勉強です。


ROSではPythonのテストはそのパッケージであるunittestを使ってテストするのが標準のようです。
C++はgtestというgoogleが作ったテスト環境を使っています。

pythonのunittestもよく分かっていないので、その勉強からです。

↓のへんを読みました。


ようするに
unittest.TestCaseクラスにメソッドを定義しておくと、それを順に呼んでくれる。
assert_, assertRaises, assertEqualsなどを使って結果が想定どおりかどうかを確かめる。
テスト前に呼ばれるsetUp(), テスト後に呼ばれるtearDown()というメソッドが使える。

という感じですかね。(他にも機能はいっぱいあります)

普通テストドライバで関数呼び出しをずら〜っと手書きすると思いますが、
その辺の自動化と結果のレポートをしてくれるようです。

さっそくルンバのインタフェースプログラムに使いました。

TestRoombaOpen, TestRoombaCommand
という二つのテストケースクラスを作ったとすると、
テストプログラムから
test_support.run_unittest(TestRoombaOpen, TestRoombaCommand)

として呼び出すと思いますが、
rostestの場合は、

import rostest
rostest.unitrun('test_roombaif', sys.argv[0], TestRoombaOpen)
rostest.unitrun('test_roombaif', sys.argv[0], TestRoombaCommand)

とするみたいです。

そして、
CMakeList.txtに
rosbuild_add_pyunit(test/test_roombaif.py)
を追加します。

この状態で
$ make test
するとテストが実行され、結果が
~/.ros/test_results/otl_roomba/test_roombaif.py.xml
として保存されます。

中身は↓みたいな感じです。
<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="35" time="17.229">
  <testcase classname="__main__.TestRoombaCommand" name="test_ascii" time="0.6085"></testcase>
......
  <testcase classname="__main__.TestRoombaCommand" name="test_vel9" time="0.5080"></testcase>
  <system-out><![CDATA[speed limit over -501 < -500
rad limit over -2001 < -2000
speed limit over 501 > 500
rad limit over 2001 > 2000
speed limit over -501 < -500
rad limit over -2001 < -2000
]]></system-out>
  <system-err><![CDATA[]]></system-err>
</testsuite>

これは単体テスト(ROSノード無関係)用です。

いっぽうでROSノードレベルのテストをする場合は以下のようにして呼び出します。
rostest.rosrun(PKG, 'test_bare_bones', TestBareBones)

あとはrostestを使ったテストですがこれはまた次回にしましょう。

0 件のコメント:

コメントを投稿