如何在Midje中定义先决条件函数?

时间:2017-09-15 17:40:36

标签: clojure tdd midje

我首先应该说我是Clojure的新手,以及一般的FP。我一直在阅读有关如何在Midje中定义先决条件的文档,但我无法理解其中的一些内容。

我的理解是,要做自上而下的TDD,您应该首先在测试模块中编写测试,并在顶部添加unfinished语句,声明'声明&#39 ;您尚未定义的所有先决条件功能。然后你可以在测试中的provided函数中调整那些先决条件函数(描述它们的返回值等)。

我的困惑在于您应该如何让您的实际源模块识别必备功能。这是一个非常简单和人为的例子,我将用它来说明我的意思:

    ;;; in my run_game_test module

    (ns clojure-ttt.run-game-test
      (:require [midje.sweet :refer :all]
                [clojure-ttt.run-game :refer [start-game]]))

    (unfinished do-turns)

    (fact "`start-game` returns whatever `do-turns` returns"
      (start-game) => ..winner..
      (provided
        (do-turns) => ..winner..))

然后为了使测试失败,我只是在我的run_game模块中写了一个函数的存根。

    (ns clojure-ttt.run-game)

    (defn start-game
      [])

到目前为止一切顺利。我运行测试但他们失败了因为:
a)do-turns没有被召唤 b)start-game没有返回任何内容。

现在通过更改start-game来调用并返回(do-turns)来进行测试。为了记录,do-turns是一个假设的先决条件函数,我将从一个尚未存在的模块中获取 - 据我所知,这是自上而下的TDD工作原理。

    (defn start-game
      []
      (do-turns))

现在,可以理解,我收到了一个巨大的错误; Clojure无法解析符号do-turns。所以我想,也许如果我(declare do-turns)在顶部,我可以防止它爆炸。不,我得到了一个不同的错误,因为我试图调用一个未绑定的函数。

我尝试了几种让Clojure识别do-turns的方法,但似乎unfinished声明给出了问题。我只是使用unfinished错了吗?

1 个答案:

答案 0 :(得分:1)

来自Midje docs

  

unfinished类似于Clojure的declare,因为它可以采用多个参数并为每个参数定义一个var。与declare不同,它将var绑定到一个函数,该函数在被调用时会被炸毁

因此当您执行(unfinished do-turns)然后使用(do-turns)调用它时会抛出异常:

  

错误#'do-turns [var]没有实现,但它被调用如下:   (do-turns) midje.util.exceptions / user-error(exceptions.clj:13)

您可以通过删除(unfinished do-turns)部分并提供do-turns的实施来解决此问题。如,

(ns clojure-ttt.run-game)

(defn do-turns)
  [])

(defn start-game
  []
  (do-turns))

并在测试中引用它

(ns clojure-ttt.run-game-test
  (:require [midje.sweet :refer :all]
            [clojure-ttt.run-game :refer [start-game do-turns]])) ; <- do-turns

;; Remove `(unfinished do-turns)` since it is no longer unfinished

(fact "`start-game` returns whatever `do-turns` returns"
  (start-game) => ..winner..
  (provided
   (do-turns) => ..winner..)) 
;; => returns true

请注意,当您提供do-turns的实现时,(unfinished do-turns)将抛出异常,因为实现已存在,因此将其删除。

现在您已经证明对(start-game)的调用会返回(do-turns}返回的内容。