Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
278 views
in Technique[技术] by (71.8m points)

clojurescript - How can I get Clojure :pre & :post to report their failing value?

(defn string-to-string [s1] 
  {:pre  [(string? s1)]
   :post [(string? %)]}
  s1)

I like :pre and :post conditions, they allow me to figure out when I have put "square pegs in round holes" more quickly. Perhaps it is wrong, but I like using them as a sort of poor mans type checker. This isn't philosophy though, this is a simple question.

It seems in the above code that I should easily be able to determine that s1 is a function argument in the :pre condition. Similarily, % in the :post condition is always the function return value.

What I would like is to print the value of s1 or % when either of these respective conditions fail within the AssertionError. So I get something like

(string-to-string 23)

AssertionError Assert failed: (string? s1) 
(pr-str s1) => 23 

With the AssertionError containing a single line for every variable that was identified as being from the function argument list and that was referenced in the failing test. I would also like something similar when the return value of the function fails the :post condition.

This would make it trivial to quickly spot how I misused a function when trying to diagnose from the AssertionError. It would at least let me know if the value is nil or an actual value (which is the most common error I make).

I have some ideas that this could be done with a macro, but I was wondering if there was any safe and global way to basically just redefine what (defn and (fn and friends do so that :pre and :post would also print the value(s) that lead to the test failing.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You could wrap your predicate with the is macro from clojure.test

(defn string-to-string [s1] 
  {:pre  [(is (string? s1))]
   :post [(is (string? %))]}
 s1)

Then you get:

(string-to-string 10)
;FAIL in clojure.lang.PersistentList$EmptyList@1 (scratch.clj:5)
;expected: (string? s1)
;actual: (not (string? 10))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...