For Development HEAD DRAFTSearch (procedure/syntax/module):

9.34 gauche.test - 単体テスト

Module: gauche.test

テストスクリプトを書くための手続きを提供します。 テストスクリプトは次のような形になります。

(use gauche.test)
(test-start "my feature")
(load "my-feature")  ; テストすべきプログラムをロード
(import my-feature)  ; モジュールを定義している場合はインポート

(test-module 'my-feature) ; モジュールの一貫性チェック

(test-section "feature group 1")
(test "feature 1-1" EXPECT (lambda () TEST-BODY))
(test "feature 1-2" EXPECT (lambda () TEST-BODY))
 ...

(test-section "feature group 2")
(define test-data ...)
(test "feature 2-1" EXPECT (lambda () TEST-BODY))
(test "feature 2-2" (test-error) (lambda () TEST-THAT-SIGNALS-ERROR))
 ...

(test-end :exit-on-failure #t)

このテストスクリプトは、バッチ処理でもインタラクティブセッションからでも 実行できます。インタラクティブセッションの場合はこのテストスクリプトを ただロードすれば、各テストの結果とサマリーが報告されます。 バッチテストの場合は、標準出力を別のファイルにリダイレクトしておくと良いでしょう。 標準出力が端末でない場合、テスト手続きは詳しい結果をstdoutに出力し、簡単な メッセージを標準エラー出力に書き出します。

モジュールやプログラムを書いたら、Makefileに"check"ターゲットを作ることを お薦めします。ルールはこんな感じになるでしょう:

check :
        gosh my-feature-test.scm > test.log

ポータブルなコードでは、テストフレームワークを定めたsrfiがあります (srfi.78 - 軽量なテスト、およびsrfi.64 - SchemeテストスイートAPI参照)。 Gaucheでは、これらのsrfiをgauche.testと一緒に使うと、 srfiのテストがGaucheのテストとして走るようになっています。


9.34.1 テストファイルの構造

Function: test-start module-name

{gauche.test} テストの状態を初期化して、ヘッダをログに書き出します。テストを呼ぶ前に呼んで下さい。 module-nameはログのために使われる文字列です。

テストが既に走っている場合は、 この手続きはログメッセージを出して内部のテストネストレベルを更新するだけです。 これにより、test-start/test-endのペアを持つスクリプトを 別のテストスクリプトからincludeすることができます。

この機能は、例えば長大なテストスクリプトをいくつかのサブテストスクリプトに 分割するのに役立ちます。各サブテストスクリプトはそれぞれ独立に走れるように しておいて、元のテストスクリプトはそれらをincludeします。 これによって、開発中は必要なサブテストスクリプトだけを走らせ、フルテストでは 全てのテストを走らせる、といった運用ができます。

Function: test-end :key exit-on-failure

{gauche.test} 失敗したテストのリストを報告します。exit-on-failure#fか 省略された場合は、この手続きは失敗したテストの数を返します。

そうでなければ、この手続きはexitを呼んでgoshを 終了させます。exit-on-failureにfixnumが渡された場合は、 それがプロセスの終了ステータスとして使われます。exit-on-failureが 他の真となる値であった場合は、終了ステータスは1となります。

テストがネストしている場合、つまりこのtest-endと対応するtest-start が、既にテストが走っている状況で実行されていた場合は、この手続きは単にログメッセージを 出力して内部のテストネストレベルを調整します。

Function: test-running?

{gauche.test} テストが実行中、つまり、一番外側のtest-starttest-endの間に いるならば#tを、そうでなければ#fを返します。

Function: test-section section-name

{gauche.test} 一群のテストの開始をマークします。単にログに使われるだけです。

Function: test-log fmtstr args …

{gauche.test} この手続きも単なるログのためのものです。 formatと同じようにfmtstrargsからフォーマット済み文字列を 作り、;; を前に、改行文字を後につけて現在の出力ポートへと出力します。

典型的なMakefileでのテスト起動では、テストスクリプトの標準出力をログに流すので、 このメッセージもログにのみ記録されることになります。

この手続きは、自動化テストで検査することは出来ないけれどトラブルシューティングに 役に立つかもしれない情報をダンプしておくのに使えます。 例えば、謎のテスト失敗報告が来て、でも手元ではどうしても再現できず、 実行システムに固有のある側面が影響しているのではないかと推測できたとしましょう。 その場合、test-logでそういった情報をダンプするコードをテストスクリプトに 仕込んでおいて、もう一度報告者のマシンでテストを走らせてもらい、そのログを解析する ことができるでしょう。

Function: test-record-file file

{gauche.test} テストスクリプトがいくつかある場合を考えます。通常は、それらのテストスクリプト をひとつづつ走らせて結果を確かめるのではなく、全部を一気に走らせて 簡単な結果のまとめだけを知りたいと思うでしょう。

test record fileはテスト結果を集積するための補助ファイルです。 その内容は次のような一行のサマリになっています。

Total:  9939 tests,  9939 passed,     0 failed,     0 aborted.

test record fileが既に存在していると、test-startは それを読みこんで数字を覚えておきます。そしてtest-endが そのスクリプト中のテスト結果の数字を加算して、同じtest record fileに書き戻します。

makefileのcheckターゲットを次のように書いておけば、 make checkを実行するたびにテスト結果の一行サマリを 得ることができます。 ただし、test1.scmtest2.scmtest3.scmはいずれも test-start呼び出し前に(test-record-file "test.record")を 評価しているものとします。

check:
        @rm -f test.record test.log
        gosh test1.scm >> test.log
        gosh test2.scm >> test.log
        gosh test3.scm >> test.log
        @cat test.record

test-record-file手続きがうまく動作するためには、それが test-startより前に呼ばれなければならないことに注意してください。

この手続きのかわりに、環境変数GAUCHE_TEST_RECORD_FILEを使って test record fileを指定することもできます。

Environment Variable: GAUCHE_TEST_RECORD_FILE

テストスクリプトが走る時にこの環境変数が指定されていれば、 その値がtest record fileの名前として使われます。

ただしテストスクリプト中にtest-record-fileの呼び出しがあると そちらが優先され、この環境変数は無視されます。

Function: test-summary-check

{gauche.test} テストレコードファイルが(test-record-fileもしくは環境変数 GAUCHE_TEST_RECORD_FILEによって)設定されていた場合、 それを読み込んで、失敗カウントとアボートカウントがともに0でなければ 終了ステータス1でexitします。テストレコードファイルが設定されていなければ 何もしません。

これは、複数のテストスクリプトを持っていて、どれかが失敗したらmakeに それを伝えたいけれども、テストスクリプト自体はすべて走らせたい、という場合に便利です。 各テストスクリプトでtest-end:exit-on-failureを 使ってしまうと、makeは失敗したテストスクリプトのところで処理を打ち切って しまいます。そこで:exit-on-failureを使うのを避け、 テストレコードファイルを使い、ビルドの最後にこの関数を呼ぶようにします:

check:
   rm -f $GAUCHE_TEST_RECORD_FILE test.log
   gosh test1.scm >> test.log
   gosh test2.scm >> test.log
   cat $GAUCHE_TEST_RECORD_FILE /dev/null
   gosh -ugauche.test -Etest-summary-check -Eexit

こうしておくとmakeは失敗があろうともすべてのテストスクリプトを 実行し (goshは常に終了ステータス0で終了するので)、 最後の行でテストレコードファイルを参照して、失敗があった場合に makeにそれを伝えることができます。


9.34.2 個々のテスト

多くのテストフレームワークでは、何をテストするかによってtest-asserttest-equalなどの様々なテスト手続きを提供しています。 Gaucheではテスト手続きはtest (およびそのラッパーであるtest*) だけです。 testはテストする式(のサンク)、期待される結果、そして省略可能な検査述語を取り、 式の実際の結果と期待される結果を検査述語で比較します。 単純に値を比較する、エラーが投げられることを確認する、など様々なテストは 検査述語によって処理されます。デフォルトの検査述語でも、 以下のような色々なテストに対応できます。

このようにしておくと、例えば期待される結果とテストサンクのリストを用意して ループするような、テストのパラメタライズが容易にできます。

Macro: test* name expected expr :optional check report hook

{gauche.test} exprをlambdaでくるんでくれる便利なマクロです。

(test* name expected expr opt ...)
  ≡ (test name expected (lambda () expr) opt ...)
Function: test name expected thunk :optional check report hook

{gauche.test} thunkを呼び、その結果がexpectedに沿っているかを checkを次のとおり呼び出すことで確認します。

(check expected result-of-thunk)

この手続きは、渡された結果が期待する値と合致する場合に#tを、 そうでなければ#fを返さなければなりません。 デフォルトのcheck手続きは下で述べるtest-checkです。 これは、expectedがいくつかの特殊なテストオブジェクトである場合をのぞき、 expectedresult-of-thunkequal? である場合に#tを返します。すなわち、通常はテスト式の結果が 期待するものとequal?であればテストは成功である、ということです。 (特別な場合については下の “曖昧な結果をテストする” および “異常系をテストする” の項を見てください)。

特別な比較手続きのひとつの用法は、非正確な数値を、多少の誤差を許して 比較するような場合です。

(test "test 1" (/ 3.141592653589 4)
      (lambda () (atan 1))
      (lambda (expected result)
        (< (abs (- expected result)) 1.0e-10)))

nameはログに残すためのテストの名前です。

thunk内で捕捉されないエラーが発生した場合、それは捕捉され、 特別なエラーオブジェクト<test-error>に置き換えられます。 その結果を、下で説明するtest-error手続きで作った<test-error> オブジェクトと比較することにより、エラーが期待されたものであるか、 また適切な例外が上がっているかをテストすることができます。

省略可能引数report#fか、引数を3つ取る手続きです。 checkが偽を返した場合に呼ばれます (ただし、hookが呼ばれる前です)。 最初の引数はname、次の引数はexpeced、最後の引数はthunkが 返した値か、thunkがエラーを投げた場合は<test-error>オブジェクトです。 デフォルトはtest-report-failure手続きで、これは単にwriteを使って 最後の引数(実際の結果、あるいは<test-error>オブジェクト)を出力するだけです。 別の手続きを与えることにより、テスト失敗時の出力をカスタマイズできます。

最後に、省略可能引数hookは、#fか4引数の手続きでなければなりません。 それが手続きの場合、testがテストを終えた後で次の引数で呼び出されます: 第1引数はシンボルpassfail、第2引数はname、 第3引数はexpected、そして第4引数は、thunkの返り値か、 thunkがエラーを投げた場合は<test-error>オブジェクト。 hookの戻り値は無視されます。

これは、gauche.testをラップしたライブラリが独自にテスト結果を記録したい 場合に便利です。

註: 0.9.10ではreport引数がありませんでした。report引数を追加するに 当たって、それを最後の省略可能引数ではなく、2番目の省略可能引数として hook引数をずらすことにしました。 hook引数は滅多に使われないだろうという判断です。 互換性のため、report引数に4引数の手続きが渡された場合は 警告を出したうえでそれをhookとして扱うコードが今は入っています。 将来のリリースではこの互換性コードは取り除かれます。

Function: test-check expected actual :optional equal

{gauche.test} テスト式の結果が期待された値に合致していることをチェックするために testtest*が使うデフォルトの手続きです。 基本的に、test-checkexpectedactualequalに渡された手続きで比較するだけです。equalの デフォルト値はequal?です。 ただし、以下に述べるとおり、expectedが特殊なテストオブジェクト だった場合には特別な振る舞いをします。

Function: test-report-failure name expected actual

{gauche.test} テスト失敗をレポートする手続きのデフォルトです。これは単に actual-resultwriteで書き出すだけです。 testtest*report引数に独自の手続きを渡すことにより、 テスト失敗時の表示をカスタマイズできます。 例えば下のtest-report-failure-diffを参照してください。

曖昧な結果をテストする

Function: test-one-of choice …

{gauche.test} 時々、テスト式exprの結果が外部の環境に左右されるため、 ひとつの確定した値を期待値expectedとして書いておけない場合があります。 この手続きはそのようなテストを簡単に書けるようにします。

choice … のいずれか を表現する特別なオブジェクトを返します。 デフォルトの検査手続きであるtest-checkは、expected引数に そのオブジェクトが渡ってきた場合には、テスト結果とchoice …を ひとつづつ照合し、どれかがマッチすれば真を返します。

例えば次のテストは、procが1か2を返せば成功となります。

(test* "proc returns either 1 or 2" (test-one-of 1 2) (proc))

test-checkは各choiceに対してtest-checkを再帰的に 呼びます。すなわち:

(test-check (test-one-of choice ...) result equal)
 ≡ (or (test-check choice result equal) ...)

従って、各選択肢を比較する手続きをカスタマイズしたい場合は、 それを与えたtest-check手続きをチェック手続きとして渡してください。 例えば次の例は、各選択肢と結果をstring-ci=?で比較します:

(test* "Using one-of with case insensitive comparison"
       (test-one-of "abc" "def")
       "Abc"
       (cut test-check <> <> string-ci=?))
Function: test-none-of choice …

{gauche.test} choice … のいずれでもない を表現する特別なオブジェクトを返します。 テストは、テスト結果がchoiceのどれにもマッチしなかった時に成功となります。

註: 非正確な数値の結果を比較したい場合は、 approx=?が使えます (数値の比較参照)。

Function: test-truthy

{gauche.test} 真の値、つまり#f以外のあらゆる値を期待するオブジェクトを返します。 テストする式が真の値を返す(が、#tとは限らない)場合に便利です。

異常系をテストする

Function: test-error :optional (condition-type <error>) (message #f)

{gauche.test} 与えられたcondition-typeと適合する<test-error>オブジェクト とマッチするような、新たな<test-error>オブジェクトを作成して返します。

テスト結果をチェックするtest-check手続きは<test-error>オブジェクトを 特別に扱います。err-expectederr-actualが ともに<test-error>のインスタンスであるとき、 (test-check err-expected err-actual)err-expectedの持つcondition typeがerr-actualの それと同じであるか、スーパータイプである場合に#tを返します。

例えばfooの呼び出しが<io-error> (もしくはそのサブタイプ) の コンディションを投げるかどうかをテストしたければ、次のように書くことができます。

(test "see if foo raises <io-error>" (test-error <io-error>) (foo))

もう一つの省略可能引数messageは、テスト中に投げられたエラーの メッセージが期待するパターンを満たしているかどうかをチェックするのに使います。 この引数は文字列、正規表現、#fのいずれかでなければなりません。 この引数が文字列の場合、test-checkは投げられたエラーのメッセージが その文字列と完全に一致するかどうかをチェックします。 この引数が正規表現の場合、test-checkは投げられたエラーのメッセージが その正規表現にマッチするかをチェックします。 デフォルトは#fで、その場合はメッセージのチェックは行われません。

Variable: *test-error*

{gauche.test} Deprecated. condition typeとして<error>を持つ<test-error> オブジェクトに束縛されています。この変数は互換性のためにのみ残されています。 新しいコードは上に述べたtest-error手続きを使ってください。

Variable: *test-report-error*

{gauche.test} この変数が真であれば、testルーチンはエラーを捕捉した際に スタックトレースをカレントエラーポートに出力します。 期待しない状況でtest-errorオブジェクトが返された際に、そのエラーが どこで起こったかを知るのに役立つでしょう。

この変数はgauche.testモジュールが読み込まれた時点で 環境変数GAUCHE_TEST_REPORT_ERRORの値により初期化されます。 例えば、テストスクリプト中の予期せぬエラーを調べるのに、 次のようにすることができるでしょう (環境変数がセットされていれば、値は関係ありません)。

env GAUCHE_TEST_REPORT_ERROR=1 gosh mytest.scm

9.34.3 外部のテストの取り込み

しばしば、既存の仕様を実装していて、テストコードがその仕様に付属していることがあります。 テストがR7RSで書かれていればそれ自体をGaucheで実行することはできますが、 gauche.testで管理されるより大きなテストスイートの一部として 与えられたテストを実行したい場合もあるでしょう。 Gaucheではテスト用SRFIであるsrfi.64srfi.78gauche.test と連携するようになっているので、テスト結果がまとめて報告されます。

ただ、テストがR7RS形式で書かれている場合、それをGaucheのテストスイートに 単純にincludeするだけではうまくいかないことがあります。 GaucheにもともとあったimportとR7RSのimportは異なっているので、 Gaucheは実行時に、 プログラム中で最初に出会うimportでどちらかを切り替える黒魔術を使っています (3つのimport形式参照)。 Gaucheプログラム中にR7RSプログラムをインクルードした場合、R7RSプログラム中の importがGaucheのimportと解釈されてしまうのでうまくありません。 かわりに、下のマクロtest-include-r7が使えます。

註: 外部テストがChibi Scheme向けに書かれている場合、 chibi-testが使えます(compat.chibi-test - Chibi schemeテストの実行参照)。

Macro: test-include-r7 path [exclude-clause]

{gauche.test} includeフォーム (インクルード参照) と同じように、 pathで指定されるファイルの内容をこのマクロの位置に挿入します。 pathが相対パスの場合は、インクルードしているファイルからの相対になります。

ファイル中のコードは、importがR7RSのimportに束縛された 環境で挿入されます。したがってR7RSで書かれたテストスクリプトがそのまま実行できます。

推奨される使い方は、Gaucheのテストスクリプト中に別のモジュールを作ってその中で インクルードする方法です。

(use gauche.test)
(test-start ...)
     :
(test-section "xxx-tests")
(define-module xxx-tests
  (use gauche.test)
  (test-include-r7 "xxx-tests"))

しばしば、与えられたテストスクリプトが、Gaucheにない名前でライブラリを参照 していることがあります (例えばtests/include/srfi-222-tests.scm(compounds)というライブラリをインポートしていますが、 Gaucheではそのライブラリはsrfi.222という名前で提供されています) その場合、Gaucheに無いモジュールをexclude-clauseに列挙することで、 importがそのモジュールを無視するようにできます:

(define-module srfi-222-tests
  (use gauche.test)
  (use srfi.222)
  (test-include-r7 "include/srfi-222-tests" (exclude (compounds))))

exclude-clauseは次の形式を取ります:

<exclude-clause> : (exclude r7rs-library-name ...)

9.34.4 見やすいテスト失敗の報告

上記testの項で説明したように、test手続きやtest*マクロの report引数に手続きを渡すことで、失敗の報告をカスタマイズできます。 便利なカスタマイズのひとつは、複数行に渡るテキストの差分を示すことです。 これはとても便利なので、それ用の手続きを用意しました。

これはちょっとわざとらしいテストです。 test-report-failure-diffreport引数に渡しています (それと、check引数にtest-check-diffを渡しています。後で説明します。) 期待される結果は行のリストで、実際の結果は単一の文字列になっています。 test-report-failure-difftest-check-diff手続きは、 expectedactualに渡されるものを単一の文字列へと正規化するので、 渡しやすいような形式で引数を渡すことができます。

(test* "Beatrice"
       ;; expected
        '("What fire is in mine ears?  Can this be true?"
          "Stand I condemned for pride and scorn so much?"
          "Contempt, farewell, and maiden pride, adieu!"
          "No glory lives behind the back of such.")
       ;; actual
       "What fire is in mine ears?  Can this be true?\n\
        Stand I condemn'd for pride and scorn so much?\n\
        Contempt, farewell! and maiden pride, adieu!\n\
        No glory lives behind the back of such.\n"
       test-check-diff           ; check
       test-report-failure-diff) ; report

 ⇒ Reports:
ERROR: GOT diffs:
--- expected
+++ actual
@@ -1,4 +1,4 @@
 What fire is in mine ears?  Can this be true?
-Stand I condemned for pride and scorn so much?
-Contempt, farewell, and maiden pride, adieu!
+Stand I condemn'd for pride and scorn so much?
+Contempt, farewell! and maiden pride, adieu!
 No glory lives behind the back of such.

このとおり、結果がunified diffフォーマットで報告されるので、どこが違っているのか 見つけやすくなります (unified diffフォーマットについてはtext.diff - テキストストリームの相違点を計算する参照)。

Function: test-check-diff expected actual :optional equal

{gauche.test} test手続き/test*マクロのcheck引数に渡せる チェック手続きです。

まず、expectedactualを次の規則によって正規化します。

  • 文字列のリストであれば、\nを糊としてひとつの文字列へとjoinします (suffixシンタックスを使います。つまり、最後の行の末尾にも\nは付きます)。
  • (content-of <string>)という形であれば、 <string>をファイル名と解釈し、そのファイルを読み込んだ文字列を使います。 ファイル名が相対パスの場合、現在ロードしているファイルからの相対と解釈されます。 ファイルが無ければ空文字列になります。
  • 文字列や他のオブジェクトの場合は、それがそのまま使われます。

正規化後、二つの引数がequal手続きによって比較されます。デフォルトはequal?です。

Function: test-report-failure-diff msg expected actual

{gauche.test} test手続き/test*マクロのreport引数に渡せる チェック手続きです。

まずexpectedactual引数がtest-check-diffと同様に 正規化されます。つまり、文字列のリストか(content-of <filename>)ならば 単一の文字列に変換されます。

それから、両者の差異をunified diff形式で表示します (diff-report/unifiedが使われます。 text.diff - テキストストリームの相違点を計算する参照)。

expectedactualの少なくとも一方が文字列に変換されなかった場合は、 標準のtest-report-failureと同じ表示になります。

註: この手続きは、テストが失敗した時だけでなく、test-endがテスト結果の まとめを表示する時にも呼ばれます。 従って、(content-of <filename>)の形式を使う場合は、 test-endが戻るまで<filename>が存在するようにしてください。 例えばテスト内で一時ファイルを作って結果をそこに出し、そのテスト後にクリアする、 という場合はこの形式は使い辛いでしょう。 一般的に、(content-of <filename>)形式は、expectedに あらかじめ用意してあるファイルを指定するのに使うのが良いでしょう。

Macro: test*/diff name expected expr

{gauche.test} test*マクロでtest-check-difftest-report-failure-diffcheckreport引数に指定したもので、簡便のために用意されています。

(test*/diff name expected expr)
 ≡
 (test* name expected expr test-check-diff test-report-failure-diff)

9.34.5 準静的検査

Schemeは動的型付けで、これはREPLでインクリメンタルあるいは実験的な開発を するには便利なのですが、コードが実際に走るまでエラーに気づかないということになりがちです。 しばらく走らせた後で変数名のタイポで止まってしまうと腹立ちますよね。

Gaucheでは、こういった種類のエラーをテスト時に検査する方法を用意しています。 これは完全に静的な検査ではありません(対象のモジュールやスクリプトをロードするので、 トップレベル式は実行されてしまいます)し、網羅的でもありません (複数のモジュールを見たり、実行時に追加される情報に依存するものは検査できません)。 それでも、変数名の間違いや引数の個数の誤りなどよくあるミスはこの検査で大抵見つけることが できます。

test-moduletest-script手続きはそれぞれ、 指定されたモジュールもしくはスクリプトをロードし (その過程でSchemeコードは VM命令列へとコンパイルされます)、次にコンパイルされたVMコードを走査して 以下のテストを行います。

  1. 関数内から参照されているグローバル変数は(該当モジュール内、もしくはインポートしたモジュールで) 全て定義されているか
  2. グローバル変数が関数として使われているなら、その引数の数が 関数の定義と合致しているか。
  3. autoloadに設定されている変数が実際にロードできるか。
  4. モジュールをテストしている場合、exportされているシンボルが 定義されているか。

今のところ検査はヒューリスティックで、エラーを見逃すこともあれば、 エラーでないものをエラーと報告してしまう可能性もあります。後者については、 偽陽性となるシンボルを列挙して検査から外すようにできます。

Function: test-module module :key allow-undefined bypass-arity-check

{gauche.test} モジュールをロードし、準静的な一貫性チェックを行います。 Moduleはモジュール名のシンボルかモジュールでなければなりません。

しばしば、プラットフォームやコンパイルオプションによって グローバル変数が定義されるかどうかが異なる場合があります。 コード中では実行時にその変数の存在を確認してから使うように コーディングしてあったとしても、test-moduleは そのようなロジックを追わないため、未定義変数の参照を報告して しまいます。そのような場合は、チェックから外す変数名のリストを allow-undefinedキーワード引数に渡して下さい。

引数の個数のチェックも、偽陽性のエラーをあげる可能性があります。 モジュールがロードされた後のグローバルな関数の変更を当てにしている場合などです (例えば、コード中であるジェネリックファンクションに渡されている引数の個数が、 モジュールのロード時点では不正なものだったとしても、そのコードが実行される までに該当引数のメソッドが追加されれば、正しいコードとなるわけです)。 自分のコードは確かに正しく、チェックが誤りであるような場合は、 該当関数の名前のリストをbypass-arity-checkキーワード引数に 渡してください。

Function: test-script filename :key allow-undefined bypass-arity-check compile-only

{gauche.test} filenameで指定されるスクリプトを新しい無名モジュールにロードし、 準静的な一貫性チェックを行います。 filenameはスクリプトファイル名を指定する文字列でなければなりません。

キーワード引数の意味はtest-moduleと同じです。

filename中のトップレベルフォームは評価されるので、 トップレベルフォームのアクションに依存したスクリプトは望ましくない副作用を生じるでしょう。 この検査は、スクリプトがSRFI-22形式、 つまりアクションをmain手続きから呼ぶようになっているとうまくいきます。 R7RSスクリプトはトップレベルフォームのアクションに頼らざるを得ないので この手続きではうまく検査できません。

スクリプトがuserモジュールにロードされることに依存して書かれている場合も、 この手続きではうまくいきません。

もしスクリプトに副作用があるトップレベルフォームが書かれていて、それを 変更することができないなら、compile-onlyキーワード引数に 真の値を渡してみてください。すると、test-scriptは スクリプトのトップレベルフォームをコンパイルだけしてから静的検査を行います。 (デフォルトのloadはコンパイルだけではなく実行も行います)。



For Development HEAD DRAFTSearch (procedure/syntax/module):
DRAFT