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