LispUnit is a simple xUnit test framework for CommonLisp. See http://www.cliki.net/lisp-unit
For a description of the many test frameworks for CommonLisp see http://www.cliki.net/Test%20Framework
Like Sunir, I'm not TestInfected, though I'd like to be. My main method is TestingByPokingAround as I go, and since I mostly program in Lisp and Erlang which makes it easy to interactively poke at functions as I write them. It would be nice, though, if I collected these tests instead of using them interactively and then losing them. I'm a very lazy guy (I don't just mean that in the usual "good programmer" sense) so there is no point in my trying to discipline myself to write such fine-grained tests.
I was just thinking that what I'd really need is to be able to write something as a "unit test" just as easily as I'd write it as a throw away function. Half way through pondering how unfair it is that it's not so easy, I realised that it's trivial to extend Lisp to make it so. What I need are compile-time assertions, which run when the program is compiled/evaluated and cause a compiler error if they aren't satisfied. Suppose I'm writing a "map" function:
[This is actually Scheme.]
;; Build a new list by applying `fn' to each element of `ls' (define (my-map fn ls) (if (null? ls) '() (cons (fn (car ls)) (my-map fn (cdr ls)))))Then straight after this I scribble some tests by using some example expressions and saying what values I expect from them:
(unit-test (my-map length '((a) (b c) (d e f))) => '(1 2 3)) (unit-test (my-map (lambda (x) (impossible)) '()) => '()) (unit-test (my-map even? '(1 2 3 4)) => '(#t #t #t #t))Now when I try to compile the file, I get:
#<ERROR Unit test failed: (my-map even? (quote (1 2 3 4))) => (#f #t #f #t)>Of course my last unit test is wrong and the function is correct, because 1 and 3 are not even numbers. I revise the test to expect '(#f #t #f #t) and then it compiles smoothly.
Not a very flashy setup, but perhaps this is convenient enough to get me TestInfected. I'll start using it and let you know how I go.
Here's my unit-test macro:
(define-syntax unit-test (syntax-rules (=>) ((unit-test expr) ; assume we want #t if no expected value is given (unit-test expr => #t)) ((unit-test expr => result) (unless (equal? expr result) (error (format #f "Unit test failed: ~A => ~A" 'expr expr))))))-- LukeGorrie
For a CommonLisp version:
(defmacro unit-test (expr result) `(unless (equal ,expr ,result) (error (format 'nil "Unit test failed: ~A => ~A" ',expr ,expr)))) (defun add (x y) (* x y)) (unit-test (add 2 2) 4) (unit-test (add 3 1.5) 4.5) (unit-test (add -1 0.5) -0.5)
I'm new to LISP, and curious: since (Common) Lisp is a powerful language, is it possible to adapt the language to the practice of UnitTesting so that it fits like a glove? I would ask for two things: 1) a "test" form that defines a test-case scenario for a form, and 2) change the "defun" form so that it fails unless test-case forms exist for the form the user is trying to define, and they pass. This will be interesting to see, because before a new function is defined, a user will define the unit test for it first, a la:
(defun double (x) (+ x x)) >> double error: no test-cases found! (test (double 2) 4) (test (double 1) 2) (test (double 0) 0) (defun double (x) (* x x)) >> double error: 3 test-cases failed! (defun double (x) (+ x x)) >> double ok: 3 test-cases passed.-- AnonymousDonor
There is free code called "CLOS-UNIT" http://www.lme.die.supsi.ch/~pedrazz/clos-unit/ that is a direct mirror of JUnit. It works much as you gentleman have suggested here. I am using it and seems to work perfectly well.
-- Robert L. Read
I'm using the code from Peter Seibel's Practical Common Lisp (http://www.gigamonkeys.com/book/) chapter 9. It's lightweight and works well.