実践Common Lispを読んでみる7

実践Common Lisp

実践Common Lisp

今日から9章。ユニットテスト。最初の方は結構簡単に見える*1

追記

9章を読破。ユニットテスト、可能なら関数自体に埋め込みたくなるよねー。どうしたもんだろ。
→たぶん、マクロを使って、テスト可能な関数宣言マクロを定義する、なんだろうなあ。課題。
以下、ソースコード

(defun test-+ ()
  (and
   (= (+ 1 2) 3)
   (= (+ 1 2 3) 6)
   (= (+ -1 -3) -4)))
(defun test-+ ()
  (format t "~:[FAIL~;pass~] ... ~a~%" (= (+ 1 2) 3) '(= (+ 1 2) 3))
  (format t "~:[FAIL~;pass~] ... ~a~%" (= (+ 1 2 3) 6) '(= (+ 1 2 3) 6))
  (format t "~:[FAIL~;pass~] ... ~a~%" (= (+ -1 -3) -4) '(= (+ -1 -3) -4)))
(defun report-result (result form)
  (format t "~:[FAIL~;pass~] ... ~a~%" result form))
(defun test-+ ()
  (report-result (= (+ 1 2) 3) '(= (+ 1 2) 3))
  (report-result (= (+ 1 2 3) 6) '(= (+ 1 2 3) 6))
  (report-result (= (+ -1 -3) -4) '(= (+ -1 -3) -4)))
(defmacro check (form)
  `(report-result ,form ',form))
(defun test-+ ()
  (check (= (+ 1 2) 3))
  (check (= (+ 1 2 3) 6))
  (check (= (+ -1 -3) -4)))
(defmacro check (&body forms)
  `(progn
     ,@(loop for f in forms collect `(report-result ,f ',f))))
(defun test-+ ()
  (check
    (= (+ 1 2) 3)
    (= (+ 1 2 3) 6)
    (= (+ -1 -3) -4)))
(defun report-result (result form)
  (format t "~:[FAIL~;pass~] ... ~a: ~a~%" result *test-name* form)
  result)
(defmacro combine-results (&body forms)
  (with-gensyms (result)
    `(let ((,result t))
       ,@(loop for f in forms collect `(unless ,f (setf ,result nil)))
       ,result)))
(defmacro check (&body forms)
  `(combine-results
     ,@(loop for f in forms collect `(report-result ,f ',f))))
(defun test-* ()
  (let ((*test-name* 'test-*))
    (check
      (= (* 2 3) 4)
      (= (* 5 7) 35))))
(defun test-arithmetic ()
  (combine-results
    (test-+)
    (test-*)))
(defvar *test-name* nil)
(defmacro deftest (name parameters &body body)
  `(defun ,name ,parameters
     (let ((*test-name* (append *test-name* (list ',name))))
       ,@body)))
(deftest test-+ ()
    (check
      (= (+ 1 2) 3)
      (= (+ 1 2 3) 6)
      (= (+ -1 -3) -4)))
(deftest test-* ()
    (check
      (= (* 2 3) 4)
      (= (* 5 7) 35)))
(deftest test-arithmetic ()
  (combine-results
    (test-+)
    (test-*)))
(deftest test-math ()
  (test-arithmetic))

http://dl.getdropbox.com/u/228440/veleno-samples/lisp-samples/sample.lisp

*1:…全部理解できるのか、とか言われると不安かも