Note that assert-same requires the expected value before the test-value. This is needed for pretty, pretty messages when the assert fails:
Maybe I'm just tired, but I first took this to mean that it was impossible for assert-same to be defined so that its arguments were (actual expected (o fail-message)). Now I realize that you just mean the positions of your expected/actual values are important.
One design thought: the name assert isn't taken by Arc. You could simplify the interface while generalizing it by just separating assert from the things it's asserting.
So, the basic assert would essentially be assert-t, and the other three could follow. Something like
(assert-t actual (o fail-message))
; becomes
(assert actual (o fail-message))
; or, without the custom message
(assert actual)
(assert-nil actual (o fail-message))
; becomes
(assert (no actual) (o fail-message))
; or, without the custom message
(assert:no actual)
(assert-error actual (o expected-error))
; becomes
(assert (error actual (o expected-error)) (o fail-message))
; or, without the custom message
(assert:error actual (o expected-error))
(assert-same expected actual (o fail-message))
; becomes
(assert (same expected actual) (o fail-message))
; or, without the custom message
(assert:same expected actual)
Then, you define error and same to "do the right things". same would probably need to throw an error when the arguments were mismatched, so that you could generate the nice message---assuming that assert would catch errors and report them as failures. error would be easy to define. Maybe something like
(mac assert (condition (o fail-message))
`(on-err (fn (c) ...fail...)
(fn () (unless ,condition ...fail...))))
(mac same (expected actual)
(w/uniq (e a)
`(with (,e ,expected ,a ,actual)
(or (iso-that-works-on-hash-tables ,e ,a)
(err "" ',actual 'returned ,a 'wanted ,e))))) ; modulo prettiness
(mac error (expr (o expected-error))
`(on-err (fn (c) ...pass, modulo expected-error...)
(fn () ,expr ...fail if we get here without an error...)))
Thanks for the feedback, both here and on the bug in the bitbucket tracker.
I'm not sure of my feelings on changing all the asserts to be just one. On one hand, it is simpler to have just the one command. On the other, it seems like a much more complicated interface, as you would never guess how to use it from, for example, the method signature. assert-t, assert-same et. al. seem like a lower conceptual load.
It reminds me of the arguments over CL's loop macro -- who knows all of it? I can never remember how to do much of what I want. Of course, this is much simpler than loop. Maybe I'll implement it and see how it feels.