-
Notifications
You must be signed in to change notification settings - Fork 0
Facts v2
The quintessential fact makes a truth claim about some function in your program. Since sweeping truth claims are hard for a computer program to verify, facts contain concrete predictions that Midje can check. If the predictions come true, you gain confidence in the original claim.
As far as the implementation goes, a fact is a form that contains prediction forms. Here's a fact with one prediction:
(fact (+ 1 1) => 2)
Facts can have more than one prediction, and those predictions can be nested inside other code. Most typical are predictions inside a let
:
(fact
(let [expected 2]
(+ 1 1) => expected
(* 2 1) => expected
(- 3 1) => expected))
Facts can have descriptions (doc strings) that are printed as a part of a failure message:
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.
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 fact
.
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 be tabular. 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 of value-for-special-symbol substitutions. (The description can be on either the tabular
or the fact
.)
The above tabular fact is actually expanded into two facts: one where 0
is substituted for ?n
, and one where 2
is substituted. In the case of a failure, the output lists the substitutions.
Facts can have metadata. Here, for example, is metadata tagging a slow test:
(fact "check Takeuchi's number" :slow ...)
Both lein-midje and the repl tools can be told to skip :slow
tests (or to run only slow tests).
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.