Skip to content

Using metadata to filter facts

marick edited this page Oct 26, 2014 · 10 revisions

You can control which facts are checked using the repl tools or lein-midje. Lein-midje allows simple control with command-line arguments and more complex control from configuration files. All these means of control are explained here.

Metadata

You can find a complete description of metadata elsewhere. This page describes only the parts relevant to filtering facts.

Metadata is a map stored in the usual way, so you can use meta to fetch it:

user=> (meta (last-fact-checked))
{:midje/top-level-fact? true, :midje/guid "f9065fa7389750e16fe00d7ba36748f61d3e0df6", ...
 :priority 5, :slow true, :core true}

As you can see, the metadata is a mixture of Midje-generated key/value pairs (the first line) and user-defined pairs (the second). Here is how you could define a fact like the above:

(fact :slow :core {:priority 5}
  ...)

If a keyword's value is to be true, you need only mention the keyword. Otherwise, you provide the key and value in a map.

Metadata applies only to the top level

Metadata in interior facts is ignored. Consider this:

(fact "top level"
  (fact :slow
  ...))

You can't control whether the inner fact is run with its metadata. A somewhat kludgy workaround for that is fact-group:

(fact-group 
  (fact :slow "top level"
  ...))

See the metadata page for more.

Using the repl tools

The repl tools filter facts according to keyword arguments (other than :all) and function arguments.

Here is how you would would load all the facts whose :core metadata is truthy:

(load-facts :core)

Now let's suppose you use (load-facts :all) to load all the facts in your project. You can check only the ones not marked :slow like this:

(check-facts (complement :slow))

Note that the facts you wanted to check are remembered as the compendium's working set. If you change some code and want to recheck the not-slow tests, you need only type this:

(check-facts)

If you want to check all the facts with a priority higher than 3, you'd type this:

(check-facts #(> (:priority %) 3))

If more than one argument is given, any matching fact is checked. (Consider the arguments to be or'ed together.) The following will run all non-slow tests, but also slow tests with a priority greater than three.

(check-facts (complement :slow) #(> (:priority %) 3))

Autotest

You can also use filters with autotest, but you have to give an explicit :filters (or :filter) option:

user=> (autotest :filters :integration :slow)

You can combine filters with :dirs:

user=> (autotest :filter :integration :dir "test/m")

Order is unimportant.

Lein midje command-line arguments

Lein-midje filters according to arguments after the :filter keyword. The following selects tests that are core or not slow:

% lein midje :filter core -slow

Notice that, like the repl tools, multiple arguments mean "select tests that match any of these".

lein midje only allows you to specify whether a keyword is truthy or falsey. There's no way to instruct it to check all facts with a priority greater than 3.

Note that lein midje doesn't use the Unix conventions for options. Options come after the main arguments. If you wanted to check all the core facts in a particular namespace, you'd type:

% lein midje quux.f-transmogrification :filter core

Autotest

The :filter option is used in the same way as the non-autotest case:

% lein midje :autotest :filter -integration

Note that any directory arguments should precede the filter:

lein midje :autotest slowtests oldtests :filter -integration

lein midje and config files

You can change the default :fact-filter in a config file like this:

(change-defaults :fact-filter :slow)

You can then apply that config file from the command line:

% lein midje :config only-slow-tests

Config files are most useful for complicated filters. Here, for example, is a filter to check a pretty obnoxious set of facts:

(change-defaults :fact-filter (every-pred (complement :integration)
                                          :slow
                                          :priority   ; has a priority 
                                          #(< (:priority %) 3)))

If a :filter is given on the command line, it takes precedence over a :fact-filter in the config file.

Clone this wiki locally