Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 如何在Midje中定义必备功能?_Clojure_Tdd_Midje - Fatal编程技术网

Clojure 如何在Midje中定义必备功能?

Clojure 如何在Midje中定义必备功能?,clojure,tdd,midje,Clojure,Tdd,Midje,首先,我应该说我对Clojure和FP都是新手。我一直在阅读有关如何在Midje中定义先决条件的文档,但我对其中的一些内容没有理解 我的理解是,要进行自上而下的TDD,首先应该在测试模块中编写一个测试,在顶部有一个unfinished语句,该语句“声明”了所有尚未定义的必备函数。然后,您可以在测试中提供的函数中摆弄这些必备函数(描述它们的返回值等) 我的困惑在于如何让实际的源代码模块识别必备函数。下面是一个非常简单和人为的例子,我将用它来说明我的意思: ;;; in my run_gam

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

我的理解是,要进行自上而下的TDD,首先应该在测试模块中编写一个测试,在顶部有一个
unfinished
语句,该语句“声明”了所有尚未定义的必备函数。然后,您可以在测试中提供的
函数中摆弄这些必备函数(描述它们的返回值等)

我的困惑在于如何让实际的源代码模块识别必备函数。下面是一个非常简单和人为的例子,我将用它来说明我的意思:

    ;;; 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\u game
模块中编写一个函数存根

    (ns clojure-ttt.run-game)

    (defn start-game
      [])
到目前为止还不错。我运行了这些测试,但它们失败了,因为:
a)
do turns
没有被调用
b)
开始游戏
没有返回任何内容

现在要通过测试,请将
开始游戏
更改为调用并返回
(执行回合)
。作为记录,
do turns
是一个假设的先决条件函数,我将从一个尚未存在的模块中获得它——据我所知,这就是自顶向下TDD的工作原理

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

我尝试了其他几种让Clojure识别
do turns
的方法,但似乎
unfinished
语句给它带来了问题。我只是使用了未完成的
错误吗?

来自:

unfinished
与Clojure的
declare
类似,它可以接受多个参数并为每个参数定义一个var。与declare不同,它将var绑定到一个函数,如果调用该函数,该函数将崩溃

因此,当您执行
(未完成的do turns)
并使用
(do turns)
调用它时,将引发异常:

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

您可以通过删除
(未完成的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
(ns clojure-ttt.run-game-test
(:require[midje.sweet:参考:全部]
[clojure-ttt.run-game:参考[开始游戏做回合])。。赢家
(提供
(转身)=>…赢家…)
;; => 返回true
请注意,当您提供了
do turns
的实现时,
(未完成的do turns)
将引发异常,因为实现已经存在,所以它将被删除


现在,您已经演示了调用
(开始游戏)
返回
(do turns
)返回的内容。

谢谢,这很有效。我唯一担心的是,如果我把
do-turns
放在一个不同的名称空间中,这是否意味着我必须将
start game
所在的名称空间和
do-turns
所在的名称空间都导入到我的测试模块中?在OOP中,我只强调将被测试的类导入到相应的测试目录中,并模拟出依赖项。这种模式在Clojure中是不可能的吗?是的,如果
do-turns
start-game
在不同的名称空间中,您需要导入这两个名称空间或提供完全限定的名称,如
Clojure-ttt。其他名称空间/do-turns
<代码>已提供
使用,您需要访问var以覆盖它。如果你想依赖抽象,你可以使用协议。