2017-09-15 63 views
2

我应该说我是新来的Clojure开始,FP一般。我一直在阅读有关如何在Midje定义先决条件的文件,但我不能做一些它的意义。如何定义Midje的先决条件?

我的理解是要做自上而下的TDD,你应该首先在你的测试模块中写一个测试,在上面声明一个unfinished声明'声明'你没有定义的所有先决条件函数然而。然后你就可以在你的测试中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 
     []) 

到目前为止好。我进行的测试,他们失败的原因:
一)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

Midje docs

unfinished类似于Clojure的declare,它可以采取多个参数,并定义它们中的每一个变种。不同于声明,它结合了var来好象叫

所以当你做(unfinished do-turns),然后用(do-turns)调用它抛出一个异常,吹拂了一个功能:

错误#'do-turns [使用var]有没有实现,但它被称为是这样的: (do-turns) midje.util.exceptions /用户错误(exceptions.clj:13)

您可以通过删除(unfinished do-turns) PA解决这个问题rt并提供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)返回的内容。

+1

谢谢,这是有效的。我唯一担心的是,如果我将'do-turns'放入不同的命名空间,这是否意味着我将不得不将导入到我的测试模块中的'start-game'所在的命名空间和'do-turns'命名空间“生活?在OOP中,我只着重于将被测试的类导入相应的测试目录,并嘲笑依赖关系。这种模式在Clojure中是不可能的吗? –

+1

是的,如果'do-turns'和'start-game'在不同的命名空间中,则需要导入这两个命名空间或给出完全限定的名称,如'clojure-ttt.other-namespace/do-turns'。 'provided'使用['with-redefs'](https://clojuredocs.org/clojure.core/with-redefs),你需要访问var来覆盖它。如果你想依赖抽象,你可以使用协议。 –

相关问题