ユニットテストを書く
gauche.testライブラリを使ってユニットテストを作れます。
例えば、二乗を計算する関数squareのテストを書いてみましょう。
squareの定義(実はバグがあります):
(define (square n) (+ n n))
squareのユニットテスト:
(use gauche.test)
(test-start "square test")
;;一つ目のテスト群
(test-section "test group 1")
(test* "square 3" 9 (square 3))
(test* "square -2" 4 (square -2))
;;二つ目のテスト群
(test-section "test group 2")
(test* "pass string argument" *test-error* (square "a"))
(test-end)
このユニットテストでは三つのテストを用意しています。
一つ目は3の二乗が9であることを、二つ目は-2の二乗が4であることをテストしています。
三つ目は、引数に文字列を渡したときにエラーが起きることをテストしています。
テストの始まりにはtest-start、終わりにはtest-endを必ず書きます。
test-startの引数に書いた文字列はテスト実行時にプリントされるテストログに使われます。
test-sectionを使ってテストを分類するとたくさんのテストがあるときにテストログを分かりやすくできます。
test*はテストを行うマクロです。引数は左から順に、テスト名、期待する結果、テストする式です。
テストする式の結果と期待する結果を比較し、結果が#tなら成功、#fなら失敗します。
オプション引数compareで比較を行う手続きを指定できます。compareを指定しないとequal?を使って比較が行われます。
このマクロはtest関数に展開されます。test関数はテストする式をthunk(引数無しの手続き)の形で書かなければいけないので、test*マクロを使ったほうが楽に書けます。
test関数でテストを書いた場合はこのようになります。
(test "square 3" 9 (lambda () (square 3)))
期待する結果に*test-error*変数を使うと、エラーが起きることを確認するテストを作れます。
それでは、実際にユニットテストを行うスクリプトファイルを作りましょう。
テスト対象のsquareの定義をsquare.scm、ユニットテストをtest-square.scmに書くことにします。二つのファイルは同じフォルダ内に置いてください。
test-square.scm:
(use gauche.test)
(add-load-path ".")
(load "square")
(test-start "square test")
;;一つ目のテスト群
(test-section "test group 1")
(test* "square 3" 9 (square 3))
(test* "square -2" 4 (square -2))
;;二つ目のテスト群
(test-section "test group 2")
(test* "pass string argument" *test-error* (square "a"))
(test-end)
テストを始める前に、テスト対象のsquare関数をloadしています。
add-load-pathでユニットテストファイルと同じ場所にあるsquare.scmをロー
ドできるようにしています。ファイルをloadするとsquareの定義が読み込まれます。テスト対象のファイルがモジュール化されているなら、loadの代わりにuseを使うといいでしょう。
それではユニットテストファイルを実行してみましょう。テスト結果がプリントされます。
テスト結果:
$ gosh test-square.scm
Testing square test ...
<test group 1>-----------------------------------------------------------------
test square 3, expects 9 ==> ERROR: GOT 6
<test group 2>-----------------------------------------------------------------
test square -2, expects 4 ==> ERROR: GOT -4
test pass string argument, expects #<error> ==> ok
failed.
discrepancies found. Errors are:
test square 3: expects 9 => got 6
test square -2: expects 4 => got -4
二つのテストに失敗してしまいました。プリントされたログをみると、3の二乗が6、-2の二乗が-4になっています。squareにバグがあるので修正しましょう。
squareの定義(バグを修正済み):
(define (square n) (* n n))
squareを修正したので、もう一回テストを実行してみましょう。
テスト結果:
$ gosh test-square.scm
Testing square test ...
<test group 1>-----------------------------------------------------------------
test square 3, expects 9 ==> ok
<test group 2>-----------------------------------------------------------------
test square -2, expects 4 ==> ok
test pass string argument, expects #<error> ==> ok
passed.
テストに成功しました。
複数のユニットテストをまとめて実行したいときにはMakefileを使うといいでしょう。
ログファイルを一つにしておくと、確認するときに便利です。
test :
gosh my-feature-test1.scm >> test.log
gosh my-feature-test2.scm >> test.log
gosh my-feature-test3.scm >> test.log
by yusei