2017-09-15 13 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 
     []) 

これまでのところとても良いです。私はテストを実行すると、失敗します:
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を間違って使用していますか? Midje docsから

答えて

1

unfinishedはClojureののdeclareそれは複数の引数を取り、それらのそれぞれのためのVARを定義することができるという点で似ています。宣言とは異なり、それはあなたが(unfinished do-turns)を行い、その後、例外がスローされた(do-turns)でそれを呼び出すときに

呼び出された場合、最大吹く機能にVARをバインド:

エラー#'do-turns [VAR]ました実装ませんが、それはこのように呼ばれていた無: (do-turns) midje.util.exceptions /ユーザー・エラー(exceptions.clj:13)

あなたは(unfinished do-turns) PAを削除することによってこの問題を解決することができますそしてdo-turnsの実装を提供します。例えば。、

(ns clojure-ttt.run-game) 

(defn do-turns) 
    []) 

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

、あなたがdo-turnsの実装を提供してきたときに、(unfinished 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 

ノートでそれを参照してください。

これで、(start-game)への呼び出しで返される値は(do-turnsです。

+1

ありがとうございます。私の唯一の懸念は、 'do-turns'を別の名前空間に入れると、' start-game'が存在する名前空間とdo-turnsがある名前空間の両方をテストモジュールにインポートする必要があるということです'生きる? OOPでは、テスト対象のクラスを対応するテストディレクトリにインポートするだけで、依存関係を模擬することができます。そのパターンはClojureでは不可能ですか? –

+1

'do-turns'と' start-game'が異なる名前空間にある場合、両方の名前空間をインポートするか、 'clojure-ttt.other-namespace/do-turns'のような完全修飾名を与える必要があります。 '提供される'は['with-redefs'](https://clojuredocs.org/clojure.core/with-redefs)を利用し、それを上書きするにはvarにアクセスする必要があります。抽象化に依存したい場合は、プロトコルを使用できます。 –

関連する問題