使用 deftest 测试集合项
Testing collection items using deftest
我正在尝试使用 clojure.test 和 deftest 宏编写一些测试。
(deftest a-test
(for [item collection]
(is (= (f item) :a-value))))
但我意识到这不是执行此测试的正确方法。我搜索了文档并找到了 'are' 宏,但我不确定在这些情况下如何使用它。
编写此类测试的首选方法是什么?
您的测试不起作用的原因是 for
只是构建了一个惰性序列;它不像其他编程语言那样是命令式循环。您可以通过多种方式重写此测试。
使用 every?
函数 测试集合中的所有项目是否满足谓词。这可能是最少的代码,但缺点是如果测试失败,您将不知道是哪个特定项目失败了。
(deftest a-test
(is (every? #(= (f %) :a-value) collection)))
使用 are
. 重写测试 如果被测试的集合中的项目是硬编码列表,这是一个不错的选择,并且稍微更惯用特定于此测试的输入。
(deftest a-test
(are [item] (= (f item) :a-value)
:a
:b
:c
;; other collection items here...
))
最后,您可以 将 for
替换为 doseq
。这对于编写测试来说不太习惯,但它的优点是它可以处理以编程方式生成的测试输入集合。
(deftest a-test
(doseq [item collection]
(is (= (f item) :a-value))))
如果不了解您要解决的问题的更多细节,很难说您应该使用什么,但我可以给您一些 可能 有用的可能性,具体取决于关于实际的潜在问题是什么。
如果(正如我所怀疑的那样)您在 for
的懒惰方面遇到麻烦,一个简单的更改可以确保懒惰不会咬住您(可能已经没问题了)将更改 for
到 doseq
.
例如,
(deftest b-test (for [item (range 100)] (test/is (< item 80))))
会由于for
生成的序列的惰性而通过,这不是循环而是列表理解。这可能不是我想要的。但是
(deftest c-test (doseq [item (range 100)] (test/is (< item 80))))
会有一堆失败(每一项大于或等于 80)。请注意,唯一的区别是 for
-> doseq
.
are
是关于提供传递给定谓词的不同输入和输出,因此假设 :a-value
可以在 f
的应用程序中有所不同,这可能是有用的:
(deftest a-test
(are [x y] (= x y)
(f item-1) :value-1
(f item-2) :value-2
(f item-3) :value-3))
另一方面,如果 collection
的每个成员在应用 f
时都应该有相同的结果,那么这样说会更简洁:
(deftest a-test
(is (every? (fn [item] (= (f item) :a-value))
collection)))
我正在尝试使用 clojure.test 和 deftest 宏编写一些测试。
(deftest a-test
(for [item collection]
(is (= (f item) :a-value))))
但我意识到这不是执行此测试的正确方法。我搜索了文档并找到了 'are' 宏,但我不确定在这些情况下如何使用它。
编写此类测试的首选方法是什么?
您的测试不起作用的原因是 for
只是构建了一个惰性序列;它不像其他编程语言那样是命令式循环。您可以通过多种方式重写此测试。
使用 every?
函数 测试集合中的所有项目是否满足谓词。这可能是最少的代码,但缺点是如果测试失败,您将不知道是哪个特定项目失败了。
(deftest a-test
(is (every? #(= (f %) :a-value) collection)))
使用 are
. 重写测试 如果被测试的集合中的项目是硬编码列表,这是一个不错的选择,并且稍微更惯用特定于此测试的输入。
(deftest a-test
(are [item] (= (f item) :a-value)
:a
:b
:c
;; other collection items here...
))
最后,您可以 将 for
替换为 doseq
。这对于编写测试来说不太习惯,但它的优点是它可以处理以编程方式生成的测试输入集合。
(deftest a-test
(doseq [item collection]
(is (= (f item) :a-value))))
如果不了解您要解决的问题的更多细节,很难说您应该使用什么,但我可以给您一些 可能 有用的可能性,具体取决于关于实际的潜在问题是什么。
如果(正如我所怀疑的那样)您在 for
的懒惰方面遇到麻烦,一个简单的更改可以确保懒惰不会咬住您(可能已经没问题了)将更改 for
到 doseq
.
例如,
(deftest b-test (for [item (range 100)] (test/is (< item 80))))
会由于for
生成的序列的惰性而通过,这不是循环而是列表理解。这可能不是我想要的。但是
(deftest c-test (doseq [item (range 100)] (test/is (< item 80))))
会有一堆失败(每一项大于或等于 80)。请注意,唯一的区别是 for
-> doseq
.
are
是关于提供传递给定谓词的不同输入和输出,因此假设 :a-value
可以在 f
的应用程序中有所不同,这可能是有用的:
(deftest a-test
(are [x y] (= x y)
(f item-1) :value-1
(f item-2) :value-2
(f item-3) :value-3))
另一方面,如果 collection
的每个成员在应用 f
时都应该有相同的结果,那么这样说会更简洁:
(deftest a-test
(is (every? (fn [item] (= (f item) :a-value))
collection)))