nedap/speced.def

spec-assertion-thrown? does not evaluate arguments in spec/nilable

lennartbuit opened this issue · 2 comments

Brief

When using spec-assertion-thrown? with a programmatic nilable spec, its spec key is not evaluated.

Repro:

(ns repro
  (:require
   [clojure.spec.alpha :as spec]
   [clojure.test :refer :all]
   [nedap.utils.spec.api :refer [check!]]))

(spec/def ::a int?)

(defn check-nilable [attr value]
  (check! (spec/nilable attr) value))

(deftest my-test
  (is (spec-assertion-thrown? (spec/nilable ::a) (check-nilable ::a "twelve"))))

Expected behavior

Expect a spec assertion to be thrown for (spec/nilable ::a)

Actual behavior

Got a spec assertion thrown for (spec/nilable attr) (note that attr is not evaluated).

Reproduction steps

Run the reproduction case above.

Suspected cause

@thumbnail pointed me to #99, which fixes this evaluation for 'bare' programmatic specs. In this case it is, however, a programmatic spec being wrapped in nilable :).

Screenshot, stacktrace, etc

Environment info

Additional links

vemv commented

Hey there!

I gave some thought to this one. Consider the following:

user> (= (clojure.spec.alpha/nilable int?)
         (clojure.spec.alpha/nilable int?))
false
user> (= (clojure.spec.alpha/nilable #{1})
         (clojure.spec.alpha/nilable #{1}))
false

So, in practice it seems you intend to compare a (spec/nilable attr) that is defined on the spot in your test ns against a different (spec/nilable attr) instance defined in the SUT ns.

The snippet above shows that cannot work?

If agreed, a simple fix would be to :pre that one doesn't pass specs other than simple symbols, keywords or sets (IIRC those 3 are the only things that will work. Ref)

I guess comparing the quoted spec is fine, the main issue is that the param isn't unquoted. e.g.

user> (= '(clojure.spec.alpha/nilable #{1})
         '(clojure.spec.alpha/nilable #{1}))
true

but right now the quoted-spec is '(spec/nilable attr) instead of '(spec/nilable ::a).