"lein test :only foo.bar.test/testme" 如果 "test-ns-hook" 已定义,则无法获取函数 "testme"?
"lein test :only foo.bar.test/testme" not picking up function "testme" if "test-ns-hook" defined?
我已经定义了一个带有测试函数的 Clojure 命名空间,并希望通过 lein test
.
使用 Leiningen 2.9.1 运行 它们
测试功能是分层组织的。如果我只是 运行 lein test
,所有 deftest
都会被拾取,导致测试重复。例如:
(ns foo.bar.test
(:require
[clojure.test :as t]
[clojure.spec.alpha :as s]
[foo.bar.main :as sut])) ; system under test
(t/deftest test-strip-empty
(t/is
(s/valid? ::sut/a-spec some-value)))
(t/deftest test-strip-several-squares
(t/is
(s/valid? ::sut/a-spec some-value)))
; collect subtests
(t/deftest testcollect-strip
(test-strip-empty)
(test-strip-several-squares))
lein test
会 运行 所有三个 deftest
条目,因此 运行 宁 test-strip-empty
和 test-strip-several-squares
两次。
函数test-ns-hook
可以定义为显式调用"top of the test tree"。
(defn test-ns-hook []
(testcollect-strip))
如果存在,lein test
只会调用 test-ns-hook
:
哪个不错!
但是一旦它存在,我就不能再运行个人测试了。
lein test :only foo.bar.test/test-strip-several-squares
lein test foo.bar.test
Ran 0 tests containing 0 assertions.
0 failures, 0 errors.
不好!!
删除 test-ns-hook
的定义,它起作用了:
lein test :only foo.bar.test/test-strip-several-squares
...
Ran 1 tests containing 1 assertions.
1 failures, 0 errors.
Tests failed.
能否通过结合这两个特征来最大化幸福感:保留 test-ns-hook
定义并能够 运行 单独测试?
不要像 testcollect-strip
那样对测试进行分组。我会称之为反模式。
您可以使用 testing
宏在单个 deftest
表单中使各个断言分层:https://clojuredocs.org/clojure.test/testing
(deftest t-math
(testing "Arithmetic"
(testing "with positive integers"
(is (= 4 (+ 2 2)))
(is (= 7 (+ 3 4))))
(testing "with negative integers"
(is (= -4 (+ -2 -2)))
(is (= -1 (+ 3 -4))))))
~/expr/demo > lein clean ; lein test
lein test _bootstrap
-------------------------------
Clojure 1.10.0 Java 12
-------------------------------
lein test tst.demo.core
Ran 2 tests containing 4 assertions.
0 failures, 0 errors.
您还可以使用 测试选择器 来 运行 只有一部分测试:
~ > lein help test
Run the project's tests.
Marking deftest or ns forms with metadata allows you to pick selectors to
specify a subset of your test suite to run:
(deftest ^:integration network-heavy-test
(is (= [1 2 3] (:numbers (network-operation)))))
Write the selectors in project.clj:
:test-selectors {:default (complement :integration)
:integration :integration}
Arguments to this task will be considered test selectors if they are keywords,
otherwise arguments must be test namespaces or files to run. With no
arguments the :default test selector is used if present, otherwise all
tests are run. Test selector arguments must come after the list of namespaces.
A default :only test-selector is available to run select tests. For example,
`lein test :only leiningen.test.test/test-default-selector` only runs the
specified test. A default :all test-selector is available to run all tests.
Arguments: ([& tests])
因此,将元数据添加到测试定义
(deftest ^:basic-math t-math
(testing "Arithmetic"
(testing "with positive integers"
(is (= 4 (+ 2 2)))
(is (= 7 (+ 3 4))))
(testing "with negative integers"
(is (= -4 (+ -2 -2)))
(is (= -1 (+ 3 -4))))))
并声明测试选择器 :basics
以获取 project.clj
中带有 :basic-math
标记的所有内容:
(defproject foo.bar "0.1.0-SNAPSHOT"
...
:test-selectors {:basics :basic-math})
现在可以 运行 只有标记为 :basic-math
的测试通过:
~ > lein test :basics
还有一个技巧需要牢记。测试代码的命名空间结构 (dirs/files) 不需要与源代码的命名空间结构相匹配。你可以有一个单一的源代码 ns super.calc
,但是有一个完整的测试命名空间层次结构。我给它们都加上一个根 tst.
前缀,我认为这比在所有东西上都加上 _test
后缀更好的命名结构:
tst.super.calc
tst.super.calc.add
tst.super.calc.add.int
tst.super.calc.add.int.pos
tst.super.calc.add.int.neg
tst.super.calc.add.float
tst.super.calc.add.float.pos
tst.super.calc.add.float.neg
tst.super.calc.mult
...
因此您可以随心所欲地获得细粒度。将它与 lein 测试选择器混合可以实现近乎无限的细粒度控制。
另外,
请查看 lein-test-refresh,我最喜欢的 lein 测试方式
我已经定义了一个带有测试函数的 Clojure 命名空间,并希望通过 lein test
.
测试功能是分层组织的。如果我只是 运行 lein test
,所有 deftest
都会被拾取,导致测试重复。例如:
(ns foo.bar.test
(:require
[clojure.test :as t]
[clojure.spec.alpha :as s]
[foo.bar.main :as sut])) ; system under test
(t/deftest test-strip-empty
(t/is
(s/valid? ::sut/a-spec some-value)))
(t/deftest test-strip-several-squares
(t/is
(s/valid? ::sut/a-spec some-value)))
; collect subtests
(t/deftest testcollect-strip
(test-strip-empty)
(test-strip-several-squares))
lein test
会 运行 所有三个 deftest
条目,因此 运行 宁 test-strip-empty
和 test-strip-several-squares
两次。
函数test-ns-hook
可以定义为显式调用"top of the test tree"。
(defn test-ns-hook []
(testcollect-strip))
如果存在,lein test
只会调用 test-ns-hook
:
哪个不错!
但是一旦它存在,我就不能再运行个人测试了。
lein test :only foo.bar.test/test-strip-several-squares lein test foo.bar.test Ran 0 tests containing 0 assertions. 0 failures, 0 errors.
不好!!
删除 test-ns-hook
的定义,它起作用了:
lein test :only foo.bar.test/test-strip-several-squares ... Ran 1 tests containing 1 assertions. 1 failures, 0 errors. Tests failed.
能否通过结合这两个特征来最大化幸福感:保留 test-ns-hook
定义并能够 运行 单独测试?
不要像 testcollect-strip
那样对测试进行分组。我会称之为反模式。
您可以使用 testing
宏在单个 deftest
表单中使各个断言分层:https://clojuredocs.org/clojure.test/testing
(deftest t-math
(testing "Arithmetic"
(testing "with positive integers"
(is (= 4 (+ 2 2)))
(is (= 7 (+ 3 4))))
(testing "with negative integers"
(is (= -4 (+ -2 -2)))
(is (= -1 (+ 3 -4))))))
~/expr/demo > lein clean ; lein test lein test _bootstrap ------------------------------- Clojure 1.10.0 Java 12 ------------------------------- lein test tst.demo.core Ran 2 tests containing 4 assertions. 0 failures, 0 errors.
您还可以使用 测试选择器 来 运行 只有一部分测试:
~ > lein help test Run the project's tests. Marking deftest or ns forms with metadata allows you to pick selectors to specify a subset of your test suite to run: (deftest ^:integration network-heavy-test (is (= [1 2 3] (:numbers (network-operation))))) Write the selectors in project.clj: :test-selectors {:default (complement :integration) :integration :integration} Arguments to this task will be considered test selectors if they are keywords, otherwise arguments must be test namespaces or files to run. With no arguments the :default test selector is used if present, otherwise all tests are run. Test selector arguments must come after the list of namespaces. A default :only test-selector is available to run select tests. For example, `lein test :only leiningen.test.test/test-default-selector` only runs the specified test. A default :all test-selector is available to run all tests. Arguments: ([& tests])
因此,将元数据添加到测试定义
(deftest ^:basic-math t-math
(testing "Arithmetic"
(testing "with positive integers"
(is (= 4 (+ 2 2)))
(is (= 7 (+ 3 4))))
(testing "with negative integers"
(is (= -4 (+ -2 -2)))
(is (= -1 (+ 3 -4))))))
并声明测试选择器 :basics
以获取 project.clj
中带有 :basic-math
标记的所有内容:
(defproject foo.bar "0.1.0-SNAPSHOT"
...
:test-selectors {:basics :basic-math})
现在可以 运行 只有标记为 :basic-math
的测试通过:
~ > lein test :basics
还有一个技巧需要牢记。测试代码的命名空间结构 (dirs/files) 不需要与源代码的命名空间结构相匹配。你可以有一个单一的源代码 ns super.calc
,但是有一个完整的测试命名空间层次结构。我给它们都加上一个根 tst.
前缀,我认为这比在所有东西上都加上 _test
后缀更好的命名结构:
tst.super.calc
tst.super.calc.add
tst.super.calc.add.int
tst.super.calc.add.int.pos
tst.super.calc.add.int.neg
tst.super.calc.add.float
tst.super.calc.add.float.pos
tst.super.calc.add.float.neg
tst.super.calc.mult
...
因此您可以随心所欲地获得细粒度。将它与 lein 测试选择器混合可以实现近乎无限的细粒度控制。
另外,
请查看 lein-test-refresh,我最喜欢的 lein 测试方式