GNU Thales provides macroses for GNU Guile to conviently write and check unit-tests, very simular to Python doctest. Thales do not have user interface, it can be useful to you only if you write code in Guile. Here is simple example, with overview of main use cases:
;; For implementation reasons code must be in module and ;; module must be searchable in GUILE_LOAD_PATH. (define-module (overview)) (use-modules (thales seal)) (sealed mystic (1 2 *** (- 4 1)) ;; Short-cut for most common case. ;; Expected form is evaluated (1 2 *+* 3) ;; Same. Expected form is not evaluated. ((& 5 6) => 11) ;; Full form. ;; & is bound to function beeing testing. ((mystic 3 4) => 7) ;; Or it can be written in full (1 2 ** 4)) ;; This will fail and abort compilation (define (mystic x y) "Some mystic function of two arguments." (+ x y))
After we run guild compile overview.scm
and assuming, that
GUILE_LOAD_PATH is set properly.
;;; note: source file /work/thales/doc/examples/overview.scm ;;; newer than compiled <cutted-to-fit-page> Checking seals with & = mystic... Compilation aborted: seal broken when evaluating (mystic 1 2) Expect: (values 4) Actual: (values 3)
Ignore first two commented lines, they are leaky implementation
detail. Next comes information what function is getting tested now, and,
if test fails, pretty-printed evaluated expression, expected and actual
values. Form (values 4)
means that function returned value. If it
would throw, (throw key arg1 arg2)
would be printed.
Now, lets fix code and view another use-case. Here is fixed source:
;; For implementation reasons code must be in module and ;; module must be searchable in GUILE_LOAD_PATH. (define-module (overview-fixed) #:export (mystic)) (use-modules (thales seal)) (sealed mystic (1 2 *** (- 4 1)) ;; Short-cut for most common case. ;; Expected form is evaluated (1 2 *+* 3) ;; Same. Expected form is not evaluated. ((& 5 6) => 11) ;; Full form. ;; & is bound to function beeing testing. ((mystic 3 4) => 7) ;; Or it can be written in full (1 2 *** 3)) ;; This will no more fail (define (mystic x y) "Some mystic function of two arguments." (+ x y)) (sealed not-exported (1 2 *+* 2) (0 2 *!* numerical-overflow)) ;; Expected to throw numerical-overflow (define (not-exported x y) "Some not-exported function" (/ y x))
All tests now pass, and you can notice clause, expecting exception.
Let us, run THALES_SEAL=1 guild compile overview-fixed.scm
and we
will get on stderr Guile program, that seals tests for public function
and can be checked with guild compile
, whether old tests still
pass. This can be useful, since you will change tests for internal
functions, but maybe you do not not ocassionally change public interface.
Thales is mainly intended as light-weight solution for pure function. Scheme is functional language, after all.
For full-fledged solution with test-cases, shared-state, variable definition, teardown and initialization, take a look on srfi-64(http://srfi.schemers.org/srfi-64/srfi-64.html) which, at time of reading, may be part of Guile.