||1 month ago|
|LICENSE||3 months ago|
|README.md||1 month ago|
|examples.lisp||1 month ago|
|package.lisp||4 months ago|
|testiere.asd||4 months ago|
|testiere.lisp||1 month ago|
A testiere is armor for the head of a horse.
Testiere is a Common Lisp library for putting "protection" (tests) in the "head" of functions.
Embed tests inside function defintions. Tests are run when you compile a function, signalling errors when they fail. Great for running tests during interactive development!
A work in progress. But here is the basic idea:
(defun+ fibble (x y &key (z 10)) "Hey, a docstring." :tests (= (1 2) 13) (>= (1 2 :z 1) -5) (:outputp (0 0 :z 0) (lambda (result) (equalp result 0))) (:fails ("strings" "ain't" :z "numbers")) :end (+ x y z))
Here we define a function with four embedded tests. If any of these tests fail, the function is not defined. If the funtion is already defined, it is not redefined.
The most basic tests look like
(COMPARATOR (ARG1 ARG2 ...) VALUE)
Which will call the function with the provided arguments are compare it to a VALUE.
(>= (1 2 :z 1) -5) runs the test
(assert (>= (fibble 1 2 :z 1) -5))
In addition to basic assertions on the output of functions, testire supports more elaborate vocubulary for embedding tests. Most of these look like:
(KEYWORD (ARG1 ARG2 ...) TERM)
TERM varies according to the
A few of these are
(:outputp (..ARGS...) PREDICATE)asserts that the output passes the one-argument predicate.
(:afterp (...ARGS...) THUNK)asserts that the thunk should return non-nil after the function has run. Good for testing values of dynamic variables that the function might interact with.
(:fails (...ARGS...))asserts that the function will produce an error with the given arguments.
(:signals (...ARGS...) CONDITION)where
CONDITIONis the name of a condition. Asserts that the function will signal a condition of the supplied type when called with the provided arguments.
Stubs and Bindings
Tests can also embed bindings or mock-functions aka stubs.
Binding variables looks like
(:with-bindings LET-BINDINGS TESTS)
and are useful for binding dynamic variables for use during a set of tests.
(defvar *count*) (defun+ increment-count () "Increments the *count* variable." :tests (:with-bindings ((*count* 4)) (:afterp () (lambda () (= *count* 5))) ; 5 after the first call (= () 6) ; 6 after the second (:outputp () (lambda (x) (= x 7)))) ; and 7 after the third :end (incf *count*))
:with-stubs form is similar, except that it binds temporary
values to functions that might be called by the form in
questions. Useful for mocking.
(defun just-a-function () (print "Just a function.")) (defun+ call-just-a-function () "Calls JUST-A-FUNCTION." :tests (:with-stubs ((just-a-function () (print "TEMP JUST-A-FUNCTION."))) (equal () "TEMP JUST-A-FUNCTION.")) :end (just-a-function))
In the above, the temporary redefinition of JUST-A-FUNCTION is used.