asdas asda

sadas

sadas

How to test code


Testing code

One thing is constant in any language- the need to test the code.

In this system, a set of function names of tests are stored in the *tests* global.

 (defparameter *tests* nil)

When we define tests, we are actually writing a defun while, as a side effect, we addding the name of the function to a list of known tests.

 (defmacro deftest (name params  &body body)
   "Create a defun, adding it name to the list of *tests*."
   `(progn (unless (member ',name *tests*) (push ',name *tests*))
       (defun ,name ,params ,@body)))

Running tests updates two counters: pass and P<code>. The test function runs one test while tests runs them all.

 (let ((pass 0)  
       (fail 0)) 
   (defun test (want got)
     "Run one test, comparing 'want' to 'got'."
     (labels  
        ((white (c) ; returns nil if 'c' is not white space
           (member c '(#\# #\\ #\Space #\Tab #\Newline
                       #\Linefeed #\Return #\Page) :test #'char=))
         (whiteout (s)  ; remove all white space
           (remove-if #'white s)) 
         (samep (x y) ; returns t if the blackspace of x&y, are the same
           (string= (whiteout (format nil "~(~a~)" x)) 
                    (whiteout (format nil "~(~a~)" y)))))
       (cond ((samep want got) (incf pass))
            (t                (incf fail)
                              (format t "~&; fail : expected ~a~%" want)))
       got))
   (defun tests ()
     "Run all the tests in *tests*."
     (labels ((run (x) (format t "~&;testing  ~a~%" x) (funcall x)))
       (when *tests*
        (setf fail 0 pass 0)
        (mapcar #'run (reverse *tests*))
        (format t "~&; pass : ~a = ~5,1f% ~%; fail : ~a = ~5,1f% ~%"
                pass (* 100 (/ pass (+ pass fail)))
                fail (* 100 (/ fail (+ pass fail)))))))
   )


Examples

 (deftest ?deftest1 (&aux (a 1)) 
   (test (+ a 1) 2))

In this test, we actually see a failure.

 (deftest ?deftest2 (&aux (a 1))   
   (test (+ a 1) 3))

Note in the following, that the test calls some other function.

 (deftest ?deftest3 ()
   (test (my-complicated-thing) 
     '(3 4 5)))
 (defun my-complicated-thing ()
   (member 3 '(1 2 3 4 5)))


Credits

This code was inspired by Peter Seibel's excellent defest system (see http://gigamonkeys.com/book/practical-building-a-unit-test-framework.html).


Author

Tim Menzies (tim@menzies.us)


Copyright

Share and enjoy.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.