Clone this wiki locally
Facts are the smallest form Midje checks. Here's a fact with one checkable:
(fact (+ 1 1) => 2)
Here's a slightly more complicated fact:
(fact "addition has a unit element, 0, such that (+ x 0) => x" (+ 0 0) => 0 (+ 1 0) => 1 (+ -1 0) => -1 (+ 100000 0) => 100000)
The doc string makes a universal claim, which Midje cannot verify. It can, however, evaluate and check the four checkables. Seeing them succeed will give you confidence in the claim (at least until you learn about arithmetic overflow).
In this user guide, fact doc strings are referred to as "descriptions", because they're stored in fact metadata under the key
Fact descriptions are used to create failure messages:
user=> (fact "Twice two is three" (* 2 2) => 3) FAIL "Twice two is three" at (NO_SOURCE_PATH:2) Expected: 3 Actual: 4 false
Notice that the result of the fact is
false. The result is
true only if all predictions come true.
Checkables don't have to be at the top level. Here's a checkable nested inside a
(fact (let [expected 2] (+ 1 1) => expected (* 2 1) => expected (- 3 1) => expected))
Notice that the checkables can use lexically scoped symbols.
Facts can be nested arbitrarily deeply:
user=> (facts "about arithmetic" (fact "there is addition" (+ 1 1) => 2) (fact "about subtraction" (- 1 1) => 0) ;; Couldn't think of a fact name for this... 1 => pos? -1 => neg?) true
Notice that the outermost structure was named
facts. That's not required: it's just a synonym for
All the nested descriptions are used to create the failure output:
user=> (facts "about arithmetic" (fact "twice two is three" (+ 2 2) => 3)) FAIL "about arithmetic - twice two is three" at (NO_SOURCE_PATH:3)
Facts can contain tables. That looks like this:
(tabular "ways to arrive at 2" (fact (?op ?left ?right) => 2) ?op ?left ?right + 1 1 * 1 2 / 4 2) true
That form has three parts: the symbol
tabular (and optional description), an ordinary fact with particular symbols marked as special, and a table that gives values to substitute for special symbols.
The above tabular fact is actually expanded into something like this form:
(fact "ways to arrive at 2" (fact (+ 1 1) => 2) (fact (* 1 2) => 2) (fact (/ 4 2) => 2))
While that's not wildly efficient, it allows much of the power of macroexpansion.
The hedging above ("something like this form") is because failure messages provide more information about what substitution was made than a simple expansion would.
Facts can have metadata. It's described completely in syntax and a little semantics. As an example, though, here's metadata tagging a slow test:
(fact "check Takeuchi's number" :slow ...)
Sometimes you want to use a fact as a "todo". That can be written like this:
user=> (future-fact (time np) => polynomial?) WORK TO DO at (NO_SOURCE_PATH:1)
If the fact has a description, that will also be printed.