Respeced Save

Testing library for clojure.spec fdefs

Project README

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.

Open Source Agenda is not affiliated with "Respeced" Project. README Source: borkdude/respeced
Stars
51
Open Issues
0
Last Commit
1 year ago
Repository

Open Source Agenda Badge

Open Source Agenda Rating