1

Let's say I am attempting to test an api that is supposed to handle presence or absence of certain object fields.

Let's say I have tests like so:

(def without-foo
   {:bar "17"})

(def base-request
   {:foo "12"
    :bar "17"})

(def without-bar
   {:foo "12"})

(def response
  {:foo  "12"
   :bar  "17"
   :name "Bob"})

(def response-without-bar
  {:foo  "12"
   :bar  ""
   :name "Bob"})

(def response-without-foo
  {:bar  "17"
   :foo  ""
   :name "Bob"})

(facts "blah"
  (against-background [(external-api-call anything) => {:name => "Bob"})
  (fact "base"
    (method-under-test base-request) => response)

  (fact "without-foo"
    (method-under-test without-foo) => response-without-foo)

  (fact "without-bar"
    (method-under-test without-bar) => response-without-bar))

This works as you would expect and the tests pass. Now I am attempting to refactor this using tabular like so:

(def request
  {:foo "12"
   :bar "17"})

(def response
  {:foo  "12"
   :bar  "17"
   :name "Bob"})

(tabular
  (against-background [(external-api-call anything) => {:name "Bob"})]
  (fact 
    (method-under-test (merge request ?diff) => (merge response ?rdiff))
  ?diff          ?rdiff             ?description
  {:foo nil}     {:foo ""}          "without foo"
  {}             {}                 "base case"
  {:bar nil}     {bar ""}           "without bar")

Which results in:

FAIL at (test.clj:123)
  Midje could not understand something you wrote:
    It looks like the table has no headings, or perhaps you
    tried to use a non-literal string for the doc-string?

Ultimately I ended up with:

(tabular
  (fact 
    (method-under-test (merge request ?diff) => (merge response ?rdiff) (provided(external-api-call anything) => {:name "Bob"}))
  ?diff          ?rdiff             ?description
  {:foo nil}     {:foo ""}          "without foo"
  {}             {}                 "base case"
  {:bar nil}     {bar ""}           "without bar")

Which passes. My question is. How does the tabular function differ from the facts function, and why does one of them accept an against-background while the other blows up?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Abraham P
  • 15,029
  • 13
  • 58
  • 126

1 Answers1

2

You need to have following nesting if you want to establish background prerequisites for all your tabular based facts:

(against-background [...]
  (tabular
    (fact ...)
    ?... ?...))

For example:

(require '[midje.repl :refer :all])

(defn fn-a []
  (throw (RuntimeException. "Not implemented")))

(defn fn-b [k]
  (-> (fn-a) (get k)))

(against-background
  [(fn-a) => {:a 1 :b 2 :c 3}]
  (tabular
    (fact
      (fn-b ?k) => ?v)
    ?k ?v
    :a 1
    :b 3
    :c 3))

(check-facts)
;; => All checks (3) succeeded.

If you want to have a background prerequisite per each tabular case you need to nest it as following:

(tabular (against-background [...] (fact ...)) ?... ?...)

It's important to have the table just under tabular level, not nested in against-background or fact.

For example:

(require '[midje.repl :refer :all])

(defn fn-a []
  (throw (RuntimeException. "Not implemented")))

(defn fn-b [k]
  (-> (fn-a) (get k)))

(tabular
  (against-background
    [(fn-a) => {?k ?v}]
    (fact
      (fn-b ?k) => ?v))
  ?k ?v
  :a 1
  :b 2
  :c 3)

(check-facts)
;; => All checks (3) succeeded.

In your code it looks like the tabular data is not positioned correctly (parentheses, brackets and curly braces are not balanced correctly so it's impossible to say what exactly is incorrect).

Piotrek Bzdyl
  • 12,965
  • 1
  • 31
  • 49