Clojure: expectations and Double/NaN
I'm not really a fan of Double/NaN in general, but sometimes it
seems like the least evil choice. When I find myself in one of those
cases I always hate having to write tests in a way that differs from all
the other tests in the codebase. A goal I've always had with
expectations is to keep the syntax consistent, and as a result I've
chosen to treat Double/NaN as equal to Double/NaN when in the various
Clojure data structures.
The following examples demonstrate Double/NaN being treated as equal
;; allow Double/NaN equality in a map
(expect {:a Double/NaN :b {:c Double/NaN}} {:a Double/NaN :b {:c Double/NaN}})
;; allow Double/NaN equality in a set
(expect #{1 Double/NaN} #{1 Double/NaN})
;; allow Double/NaN equality in a list
(expect [1 Double/NaN] [1 Double/NaN])
jfields$ lein expectations
Ran 3 tests containing 3 assertions in 32 msecs
0 failures, 0 errors.As you would expect, you can also count on Double/NaN being considered equal even if you are using the 'in' function.;; allow Double/NaN equality when verifying values are in a map
(expect {:a Double/NaN :b {:c Double/NaN}} (in {:a Double/NaN :b {:c Double/NaN} :d "other stuff"}))
;; allow Double/NaN equality when verifying it is in a set
(expect Double/NaN (in #{1 Double/NaN}))
;; allow Double/NaN equality when verifying it's existence in a list
(expect Double/NaN (in [1 Double/NaN]))
jfields$ lein expectations
Ran 3 tests containing 3 assertions in 32 msecs
0 failures, 0 errors.For completeness I'll also show the examples of each of these examples failing.;; allow Double/NaN equality in a map
(expect {:a Double/NaN :b {:c Double/NaN}} {:a nil :b {:c Double/NaN}})
;; allow Double/NaN equality with in fn and map
(expect {:a Double/NaN :b {:c nil}} (in {:a Double/NaN :b {:c Double/NaN} :d "other stuff"}))
;; allow Double/NaN equality in a set
(expect #{1 Double/NaN} #{1 nil})
;; allow Double/NaN equality with in fn and set
(expect Double/NaN (in #{1 nil}))
;; allow Double/NaN equality in a list
(expect [1 Double/NaN] [1 nil])
;; allow Double/NaN equality with in fn and list
(expect Double/NaN (in [1 nil]))
jfields$ lein expectations
failure in (core.clj:5) : sample.test.core
(expect {:a Double/NaN, :b {:c Double/NaN}}
{:a nil, :b {:c Double/NaN}})
expected: {:a NaN, :b {:c NaN}}
was: {:a nil, :b {:c NaN}}
:a expected: NaN
was: nil
failure in (core.clj:8) : sample.test.core
(expect {:a Double/NaN, :b {:c nil}} (in {:a Double/NaN, :b {:c Double/NaN}, :d "other stuff"}))
expected: {:a NaN, :b {:c nil}}
in: {:a NaN, :b {:c NaN}, :d "other stuff"}
:b {:c expected: nil
was: NaN
failure in (core.clj:11) : sample.test.core
(expect #{1 Double/NaN} #{nil 1})
expected: #{NaN 1}
was: #{nil 1}
nil are in actual, but not in expected
NaN are in expected, but not in actual
failure in (core.clj:14) : sample.test.core
(expect Double/NaN (in #{nil 1}))
key NaN not found in #{nil 1}
failure in (core.clj:17) : sample.test.core
(expect [1 Double/NaN] [1 nil])
expected: [1 NaN]
was: [1 nil]
nil are in actual, but not in expected
NaN are in expected, but not in actual
failure in (core.clj:20) : sample.test.core
(expect Double/NaN (in [1 nil]))
value NaN not found in [1 nil]
Ran 6 tests containing 6 assertions in 66 msecs
6 failures, 0 errors.There
always seems to be downsides to using NaN, so I tend to look for the
least painful path. Hopefully expectations provides the most pain-free
path when your tests end up needing to include NaN.
From http://blog.jayfields.com/2011/11/clojure-expectations-and-doublenan.html
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





