# Testing ## Framework Tests use a minimal SRFI-269 implementation in `(tests support)`. Three primitives — `is`, `test`, `suite` — build first-class test entities and deliver them to a pluggable runner. Definition is separated from execution. ## Running tests All tests (via Automake): make check Single file: ./pre-inst-env guile tests/test-router.scm ## Writing tests ```scheme (use-modules (tests support) (safsaf router)) ; module under test (define-suite router-tests (suite "route construction" (test "creates route with method and pattern" (let ((r (route 'GET '("users") identity))) (is (route? r)) (is (eq? 'GET (route-method r)))))) (suite "matching" (test "exact path match" ...))) (run-tests router-tests) ``` Key points: - `(is expr)` — assert expr is truthy. Returns the value on success. - `(is (pred arg ...))` — predicate form; on failure shows evaluated args. - `(test "desc" body ...)` — a single test case with one or more assertions. - `(suite "desc" body ...)` — group tests and nested suites. - `(define-suite name body ...)` — bind a suite-thunk to a variable. - `(run-tests thunk)` — run with the simple runner, print summary, exit. - Tests should be self-contained: don't depend on ordering or side effects from other tests. - Use `define` inside `test` bodies for local setup. ## Synthetic requests Many tests need Guile `` objects without a real HTTP server. Build them with `build-request` from `(web request)`: ```scheme (use-modules (web request) (web uri)) (define* (make-request method path #:optional (headers '())) (build-request (build-uri 'http #:host "localhost" #:path path) #:method method #:headers headers)) ``` Handler signature is `(request body-port) → (values response body)`. When calling handlers or wrapped handlers in tests, pass `#f` as the body-port: ```scheme (let ((resp body (wrapped (make-request 'GET "/" '()) #f))) (is (= 200 (response-code resp)))) ``` For handlers that read `current-route-params`, `parameterize` it directly.