Lisp Unit

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.

EditText of this page (last edited April 25, 2011) or FindPage with title or text search