# (sph test) test guile scheme modules and procedures. # features ## test definition * tests grouped into modules, modules composable * simple syntax for input/output * nestable assertions with concatenated titles * hooks for before/after/inbetween, custom reporters * using modules is optional ## execution * all test code compiled before running (no compile messages during run) * modules can extend runner settings * no restriction on execution strategy (e.g. repeat, parallel) * tests across multiple files can run as one with grouped output * "only" and "exclude" filters available ## interface * scheme interface: run tests from scheme (e.g. ci) * stdout reporting optional * "compact" reporting format for efficiency * reporters extendable, selected via settings ## implementation * tests are procedures * modules are r6rs libraries * functional style, no hidden state, no goops, no opaque types # asserts all accept optional title string. nested titles concatenate. ``` (assert-true (= 3 (+ 2 1))) (assert-true "addition" (= 3 (+ 2 1))) (assert-equal "addition" (+ 1 2) 3) (assert-and "group" (assert-true "a" (= 3 (+ 2 1))) (assert-equal "b" (+ 5 4) 6) (assert-true (+ 2 1))) ``` # examples ## test module file ``` (define-test-module (test module sph string) (import (sph string)) (test-execute-procedures-lambda (string-indices ("/a////b//c/d" "/") (0 2 3 4 5 7 8 10) ("abcd" "bc") (1)) (string-multiply ("a" 3) "aaa") (string-replace-string ("abcd" "bc" "") "ad"))) ``` ## compact report ``` string-indices 1 2 string-multiply 1 string-replace-string 1 ``` ## failure report ``` string-quote 1 failure string-quote 2 inp "t'est" exp "\"t'est\"x" out "\"t'est\"" ``` ## multiple modules ``` test module sph vector vector-append 1 test module sph record define-record 1 ``` # usage ## define module ``` (define-test-module (test module mymodule) (import (mymodule)) (lambda (settings) (assert-true "addition" (= 3 (+ 2 1))))) ``` ## define tests ``` (define-test (name args ...) test-result) (define-test (abc) #t) (define-test (abc args expected) #t) (define-test (abc name index args expected) #t) ``` ## run modules ``` (import (sph) (sph test)) (define settings (test-settings-default-custom path-search "modules" reporter-name (q compact))) (test-execute-modules-by-prefix #:settings settings (q (test module sph))) ``` # settings (default excerpt) ``` (define-as test-settings-default alist-q reporters test-reporters-default reporter-name (q default) search-type (q prefix) hook (alist-q procedure-before ignore procedure-after ignore) random-order? #f parallel? #f exception-strings? #t exclude #f only #f until #f) ``` # implementation notes * modules are r6rs libraries exporting `execute` * `execute :: settings -> test-result` * modules provide scope separation and names * test-result can be list/record/boolean * define-test avoids manual "test-" prefix # excluded * cps-style tests with "done" * terminal coloring * "fun" reporters * implicit multi-return values # enhancements * count tests * reporters for csv/scm * define-test-module without wrapping * test-module composition # references * mocha, trc-testing, rails testing * scheme libs: bunny-test, guile-lib unit-test, schemeunit, srfi-64, test-manager, testeez