#:g1: ptesterの紹介

Posted 2014-02-15 15:00:00 GMT

(LISP Library 365参加エントリ)

 LISP Library 365 の47日目です。

ptesterとはなにか

 ptesterは、Allegro CLのtesterのポータブル版です。

パッケージ情報

パッケージ名ptester
Quicklisp
参考サイトThe Allegro CL Test harness
CLiKihttp://cliki.net/ptester
Quickdocshttp://quickdocs.org/ptester

インストール方法

(ql:quickload :ptester)

試してみる

 どんな関数があるかは、Quickdocsで確認できます。

 詳しい使い方は、Allegro CLのページにまとまっていますが、エラー等のコンディション周りが充実しているのが特徴です。

test

 非常にシンプルで値を比較してT/NILが返るのみです。

(test 1 1)
;=>  T

多値がテストできたりもします。

(test '(1 2) (values 1 2) :multiple-values T)
;=>  T

test-warning

 警告が出るかをチェック

(test-warning (warn "foo"))
;=>  T

test-no-warning

 警告が出ないかをチェック

(test-no-warning (warn "foo"))
;=>  NIL

test-error

 エラーになるかをチェック

(test-error (car '(10)))
;=>  NIL

コンディションのメッセージもテストできます。

(test-error (error "foo: ~A" 10) 
            :format-control "foo: ~A")
;=>  T

(test-error (error "foo: ~A" 10) :format-control "foo: ~A" :format-arguments '(11)) ;=> NIL

コンディションの種類と、そのサブタイプかどうかも指定できます。

(test-error (error "foo: ~a" 10)
            :condition-type 'condition
            :include-subtypes T)
;=>  T

breakでデバッガが起動するのを抑える指定もあったりします。
…が、Allegro CLのbreakの仕様に依存しているため他の処理系では上手く動きません…

(test-error (break "foo: ~a" 10)
            :catch-breaks t
            :condition-type 'simple-break
            :include-subtypes t)
;=>  T

test-no-error

 エラーにならないかをチェック

(test-no-error (error "foo"))
;=>  NIL

with-tests

 テストをまとめて結果を表示するフォーム

*error-protect-tests*

 Tにするとフォーム内でエラーが上がってもデバッガは起動せず続行

*break-on-test-failures*

 Tにするとテスト失敗時にデバッガを起動

*test-unexpected-failures*

 予期しない失敗の数
testフォームで:known-failure引数にTを与えるとカウントされません。

*test-errors*

 失敗したテストの数

*test-successes*

 成功したテストの数

ptesterとasdf:test-systemの連携

 testerを利用するプロジェクトを幾つか眺めてみましたが、テストフレームワークという感じまでは組織化されていないためか、そのまま利用するというよりは、テスト用の関数を定義して、その中からtestを呼ぶ、という感じが多いようです。
敢えて書くなら、テスト関数 & asdf:test-opの定義というところでしょうか。

(defun run-tests (&aux (result 0))
  (with-tests (:name "example.ptester")
    (test ...)
    (test ...)
    (test-error ...)
    (test-error ...)
    (test-warning ...)
    (incf result *test-unexpected-failures*))
  (zerop result))

と書いて、

(defsystem :example.ptester
  :serial t
  :depends-on (:ptester)
  :components ((:file "package")
               (:file "example.ptester"))
  :in-order-to ((test-op (load-op :example.ptester)))
  :perform (test-op (op c) 
             (or (funcall (intern (string :run-tests) :example.ptester))
                 (error "test-op failed") )))

test-opで呼ぶ、等々

まとめ

 今回は、ptesterを紹介してみました。
Allegro CLは、ちょっとしたところで処理系依存の便利機能を入れていたりするので、処理系依存っぽくないコードでも細かい動作の違いで動かず、オヤッ?と思うことは割とあります。

 ptesterの場合は、コンディションのフォーマット引数のチェック機能とbreakでデバッガを起動しないオプションが機能しないので、SBCLで機能するようにモンキーパッチを作ってみました。

comments powered by Disqus