Skip to content

Latest commit

 

History

History
187 lines (122 loc) · 4.23 KB

README.md

File metadata and controls

187 lines (122 loc) · 4.23 KB

respeced

CircleCI Clojars Project cljdoc badge

Testing library for clojure.spec fdefs.

Rationale

This library helps verify that spec fdefs do what they are supposed to do:

  • throw errors on non-valid arguments and return values
  • not throw on valid arguments and return values

A good illustration of the intended usage of this library can be seen in tests for the speculative library, where this library originated from.

Respeced fully supports Clojure, ClojureScript and self-hosted ClojureScript.

Installation

deps.edn

respeced/respeced {:mvn/version "0.1.2"}

leiningen

[respeced "0.1.2"]

API

with-instrumentation

Instrument a function in the scope of a body. Restores instrumentation state, i.e. unstruments after the call only when the function was not instrumented before the call.

Example call:

(with-instrumentation `foo (foo 1 2 3))

with-unstrumentation

Unstrument a function in the scope of a body. Restores instrumentation state, i.e. only re-instruments after the call when the function was instrumented before the call.

Example call:

(with-unstrumentation `foo (foo 1 2 3))

caught?

Returns true if body throws spec error for instrumented fn.

Example call:

(deftest my-fdef-works
  (with-instrumentation `foo
    (is (caught? `foo (foo :some-wrong-argument))))

check-call

Applies args to function resolved by symbol. Checks :args, :ret and :fn specs. Returns return value of call if succeeded, else throws.

Example call:

(is (= [4 5 6] (check-call `foo [1 2 3])))

check

Like clojure.spec.test.alpha/check with third arg for passing clojure.test.check options.

Example call:

(check `foo {} {:num-tests 10})

successful?

Returns true if all clojure.spec.test.alpha/check tests have pass? true.

Example call:

(successful? (check `foo {} {:num-tests 10}))

Example usage

$ clj -Sdeps '{:deps {respeced/respeced {:mvn/version "0.1.2"}}}'
Clojure 1.10

user=> (require '[respeced.test :as rt])
nil

user=> (require '[clojure.spec.alpha :as s])
nil

user=> (s/fdef foo :args (s/cat :n number?) :ret number?)
user/foo

;; this function has the wrong return value according to the spec:

user=> (defn foo [n] "ret")
#'user/foo

;; rt/check-call helps with checking `:ret` and `:fn` specs:

user=> (rt/check-call `foo [1])
Execution error - invalid arguments to respeced.test$do_check_call/invokeStatic at (test.cljc:138).
"ret" - failed: number? at: [:ret]

;; change the spec:

user=> (s/fdef foo :args (s/cat :n number?) :ret string?)
user/foo

;; no error anymore:

user=> (rt/check-call `foo [1])
"ret"

;; instrument a function within a scope:

user=> (rt/with-instrumentation `foo (foo "a"))
Execution error - invalid arguments to user/foo at (REPL:1).
"a" - failed: number? at: [:n]

;; not instrumented:

user=> (foo "a")
"ret"

;; `rt/check` has a third arg for passing `clojure.test.check` options:

user=> (rt/check `foo nil {:num-tests 1})
generatively testing user/foo
({:spec #object[clojure.spec.alpha$fspec_impl$reify__2524 0x72bd06ca "clojure.spec.alpha$fspec_impl$reify__2524@72bd06ca"], :clojure.spec.test.check/ret {:result true, :pass? true, :num-tests 1, :time-elapsed-ms 1, :seed 1541249961647}, :sym user/foo})

;; validate if generative test was successful:

user=> (rt/successful? *1)
true

user=>

Tests

Requires babashka.

The tests can be called with an optional deps.edn alias argument to specify the Clojure(Script) version to load, e.g.

bb clj-tests :1.10

All tests

bb test

Clojure

bb clj-tests

ClojureScript

bb cljs-tests

License

Copyright © 2018-2022 Michiel Borkent

Distributed under the EPL License, same as Clojure. See LICENSE.