taoensso.truss

An opinionated assertions (micro) library for Clojure/Script.

get-data

clj

cljs

(get-data)
Returns current value of dynamic assertion data.

have

macro

clj

(have x)(have pred (:in) x)(have pred (:in) x & more-xs)
Takes a (fn pred [x]) => truthy, and >=1 vals.
Tests pred against each val,trapping errors.

If any pred test fails, throws a detailed `ExceptionInfo`.
Otherwise returns input val/s for convenient inline-use/binding.

Respects `*assert*`, so tests can be elided from production if desired
(meaning zero runtime cost).

Provides a small, simple, flexible feature subset to alternative tools like
clojure.spec, core.typed, prismatic/schema, etc.

Examples:

  (defn my-trim [x] (str/trim (have string? x)))

  ;; Attach arb optional info to violations using `:data`:
  (have string? x
    :data {:my-arbitrary-debug-info "foo"})

  ;; Assert inside collections using `:in`:
  (have string? :in ["foo" "bar"])

Regarding use within other macros:
  Due to CLJ-865, callsite info like line number of outer macro
  will be lost. See `keep-callsite` for workaround.

See also `have?`, `have!`.

have!

macro

clj

(have! x)(have! pred (:in) x)(have! pred (:in) x & more-xs)
Like `have` but ignores `*assert*` value (so can never be elided!).
Useful for important conditions in production (e.g. security checks).

have!?

macro

clj

(have!? x)(have!? pred (:in) x)(have!? pred (:in) x & more-xs)
Returns `true` on successful tests, and ignores `*assert*` value
(so can never be elided!).

**WARNING**: Do NOT use in `:pre`/`:post` conditions since those always
respect `*assert*`, contradicting the intention of the bang (`!`) here.

have?

macro

clj

(have? x)(have? pred (:in) x)(have? pred (:in) x & more-xs)
Like `have` but returns `true` on successful tests.
Handy for `:pre`/`:post` conditions. Compare:
  ((fn my-fn [] {:post [(have  nil? %)]} nil)) ; {:post [nil ]} FAILS
  ((fn my-fn [] {:post [(have? nil? %)]} nil)) ; {:post [true]} passes as intended

keep-callsite

macro

clj

added in v1.8.0 (2022-12-13)

(keep-callsite form)
The long-standing CLJ-865 means that it's not possible for an inner
macro to access the `&form` metadata of a wrapping outer macro. This
means that wrapped macros lose calsite info, etc.

This util offers a workaround for macro authors:
  (defmacro inner [] (meta &form))
  (defmacro outer [] (keep-callsite `(inner)))
  (outer) => {:keys [line column ...]}

set-error-fn!

clj

cljs

(set-error-fn! f)
Sets the root (fn [data-map-delay]) called on invariant violations.

with-data

macro

clj

(with-data data & body)
Executes body with dynamic assertion data bound to given value.
This data will be included in any violation errors thrown by body.

with-error-fn

macro

clj

(with-error-fn f & body)