如何在 Clojure 中测试高阶函数?
我总是可以测试一个接受值的函数,然后根据预期的值检查返回的值。
我如何使用高阶函数来做到这一点?
或者我们通常避免这样做?
如何在 Clojure 中测试高阶函数?
我总是可以测试一个接受值的函数,然后根据预期的值检查返回的值。
我如何使用高阶函数来做到这一点?
或者我们通常避免这样做?
这是一个很好的问题。为了更准确地了解这个问题:
高阶函数“采用或产生其他函数作为参数或结果”。所以有两种情况:
接受函数的函数。例子:map
, reduce
, filter
. 这些并不难测试。只需像普通函数一样提供所有参数。
返回函数的函数。例子:(fn [x] (fn [y] (+ x y)))
, (partial filter #(> % 1))
. 这些很难测试,因为我们无法直接比较函数的相等性(搜索内涵和外延相等性进行彻底讨论)。
很明显,简单地不测试并不是一个很好的策略。那么为什么不采用 Haskell 的观点,即部分应用的函数与返回函数的函数本质上是相同的——换句话说,将足够的参数传递给返回的函数以获得可以测试相等性的结果。
请注意测试中的耦合——确保您的测试用例实际上是在测试高阶函数的规范,而不仅仅是它返回的函数。
高阶函数仍会返回结果,因此您仍然可以检查它。
例如,如果你想测试map
,想想它应该做什么:它应该获取一个函数和一个集合作为参数,将所述函数应用于集合中的每个项目,返回一个新的结果集合。
因此,一种简单的测试方法是:
(is (= [1 2 3 4] (map inc [0 1 2 3]))
如果您正在测试作为另一个函数结果的高阶函数,则同样的原则适用:您只需在调用返回它的函数之后测试它返回的内容:
(defn adder [n]
(fn [x]
(+ x n)))
(is (= ((adder 10) 5) 15))
希望这可以帮助。