Testing
Test framework with groups, assertions, and structured results.
(import (sigil test))Defining Tests
Use test to define a test case and test-group to organize related tests.
(test "addition works"
(assert-equal 4 (+ 2 2)))
(test-group "String operations"
(test "concatenation"
(assert-equal "hello world" (string-append "hello" " " "world")))
(test "length"
(assert-equal 5 (string-length "hello"))))
;; Groups can be nested
(test-group "Collections"
(test-group "Lists"
(test "map doubles"
(assert-equal '(2 4 6) (map (lambda (x) (* x 2)) '(1 2 3))))))Skipping and Pending Tests
;; Skip a test (temporarily disabled, body not executed)
(test-skip "broken feature"
(assert-equal 42 (broken-function)))
;; Pending test (placeholder for future work, body not executed)
(test-pending "not yet implemented"
(assert-true (new-feature-works)))Both are counted separately in the test summary.
Assertions
Value Equality
(assert-equal expected actual) ; deep equality (equal?)
(assert-eqv expected actual) ; value equivalence (eqv?)
(assert-eq expected actual) ; object identity (eq?)(assert-equal '(1 2 3) (iota 3 1)) ; pass — deep list comparison
(assert-eqv 3.14 3.14) ; pass — numeric equivalence
(assert-eq 'foo 'foo) ; pass — symbols are internedBoolean
(assert-true val) ; passes if val is not #f
(assert-false val) ; passes if val is #f(assert-true (> 5 3))
(assert-false (member 'x '(a b c)))Null Checks
(assert-null val) ; passes if val is '()
(assert-not-null val) ; passes if val is not '()(assert-null (cdr '(1)))
(assert-not-null (filter odd? '(1 2 3)))Error Checking
(assert-error expr) ; passes if expr raises an error(assert-error (car '()))
(assert-error (error "expected failure"))Unconditional Failure
(assert-fail message) ; always fails with message(test "should not reach else branch"
(if (valid? input)
(assert-true (process input))
(assert-fail "input was invalid")))Running Tests
Every test file should end with (run-tests).
(import (sigil test))
(test "example" (assert-true #t))
(run-tests)The CLI runs all test files in the workspace:
sigil test # Run all tests (native + Sigil) sigil test --sgl # Run only Sigil tests sigil test --native # Run only native (C) tests
Test Results
run-tests produces a test-summary with aggregate results.
test-summary-total— total tests runtest-summary-passed— tests that passedtest-summary-failed— tests that failedtest-summary-skipped— tests skipped or pendingtest-summary-duration-ms— total time in millisecondstest-summary-results— list oftest-resultrecords
Each test-result has:
test-result-name— test name stringtest-result-group— group path or#ftest-result-passed?— booleantest-result-message— failure message or#ftest-result-expected/test-result-actual— values on failure
Common Patterns
Testing a Module
(import (sigil test)
(sigil json))
(test-group "json-encode"
(test "encodes string"
(assert-equal "\"hello\"" (json-encode "hello")))
(test "encodes number"
(assert-equal "42" (json-encode 42)))
(test "encodes dict"
(let ((result (json-decode (json-encode #{ a: 1 }))))
(assert-equal 1 (dict-ref result a:)))))
(run-tests)Testing Error Conditions
(test-group "input validation"
(test "rejects empty input"
(assert-error (parse-config "")))
(test "rejects missing required field"
(assert-error (parse-config "{}"))))Test File Structure
packages/my-package/
test/
test-core.sgl # Core functionality tests
test-parsing.sgl # Parser tests
test-output.sgl # Output formatting testsEach file is self-contained with its own imports and (run-tests) call.