2004年02月22日

tcltestの書き方メモ

最近tclばかりやってるけどまあいいか・・・。tclはtcltestというユニットテストできるパッケージがデフォルトで付いてくるので、それを使ってテストを書いてみる。まずは日本語マニュアル

書き方というかテスト作成の考え方はJUnitとかCppUnitと大体同じで、複数のテストを書いたテストユニットをファイルごとに作成して、それをスイートにまとめて実行するという感じです。まずはテストユニットを書きます。雛型はこんな感じです。

package require tcltest
eval tcltest::configure $argv

package require hoge

namespace eval ::hoge::test {
  test TestName TestDetail {
    expr 1+1
  } 2
  cleanupTests
}
namespace delete ::hoge::test

この例ではhogeというパッケージを(使ってないけど)テストしているつもりです。package requireだけでなくて、loadやsourceなどでテスト対象を読み込んでもいいでしょう。
test TestName TestDetail ...とあるのがテストコマンドで、ASSERT文のようなもんです。TestName TestDetailはそれぞれわかりやすい名前を書いておきます。失敗した個所の行番号とかは出ないでTestNameとTestDetailが出力されるので、TestNameにHogeTest1-1のように連番を書き、TestDetailにその説明を書くことが多いようです。同じ名前がかぶっても問題ないので、めんどくさいときはTestNameをみんな同じにしたりしてます。

このテストコマンドの書き方は省略した書き方で、正規の書き方を使ってテストコマンドごとにsetup、cleanupを使って変数の準備と後始末をしたり、プラットフォームごとに実行に制約を付けたりなどすることもできます。

テストファイル中で全てのテストの最後にtcltest::cleanupTestsを呼んでテスト結果を収集したりなどの後始末をします。ちなみにnamespaceを使っているのは、他のテストと同じインタプリタ内で実行されたときに互いに干渉しあわないようにするための工夫です。singleprocオプションでファイルごとに子インタプリタを作る方法しか使わないというならnamespaceでまとめなくてもよいと思いますが。。。

で、これをhoge.testとか拡張子を.testにして適当なディレクトリにおきます。testという名前のディレクトリを作ってそこに置くとよいと思います。あと、ファイルごとにtcltestをrequireしてるのは、この1ファイル単体だけでもテストを実行できるようにするためです。例えばtclsh hoge.testのようにすれば、1ファイル単体でテストできます。が、まあ通常はまとめて実行するスイートを作ります。スイートはall.tclという名前で、次のような簡単なスクリプトです。
package require Tcl 8.4
package require tcltest

tcltest::configure -debug 0
tcltest::configure -singleproc no
tcltest::configure -testdir [file dir [info script]]

eval tcltest::configure $argv
tcltest::runAllTests

これはrunAllTestsコマンドで、all.tclと同じディレクトリにある.testの拡張子のファイルをsourceしてテストを実行し、その結果を表示します。-singleprocは、yesの時は全ての.testファイルが同じインタプリタのスレッド(スレッドじゃないけど)で実行されます。noの時は、.testファイルごとに子インタプリタを作成してそこでテストを実行します。デフォルトはnoです。単体テストとしてならnoで使うのが良いと思います。-debugは0~3の数字でテスト実行中の詳細を表示するレベルを指定します。

で、tclsh all.tclのように実行すると、テストを実行して、その結果を表示します。

つづく。

Posted by reddog at 2004年02月22日 11:35 | プログラム