从Clojure Repl和Leiningen中运行测试

40
作为Clojure的新手,我使用Leiningen创建了一个样例项目。
lein new app first-project

这给了我这个目录

.
├── doc
│   └── intro.md
├── LICENSE
├── project.clj
├── README.md
├── resources
├── src
│   └── first_project
│       └── core.clj
├── target
│   └── repl
│       ├── classes
│       └── stale
│           └── extract-native.dependencies
└── test
    └── first_project
        └── core_test.clj

不需要修改任何文件,我可以使用以下命令成功启动唯一失败的测试:

lein test
...
Ran 1 tests containing 1 assertions.
1 failures, 0 errors.
Tests failed.

但是我无法使用 run-tests 命令从 REPL 中完成相同的操作。

lein repl
first-project.core=> (use 'clojure.test)
nil
first-project.core=> (run-tests)

Testing first-project.core

Ran 0 tests containing 0 assertions.
0 failures, 0 errors.
{:type :summary, :pass 0, :test 0, :error 0, :fail 0}

我尝试过(但不起作用)

(require 'first-project.core-test)
4个回答

70

使用 lein repl 启动 REPL,然后使用 require 命令。


(require '[clojure.test :refer [run-tests]])
(require 'your-ns.example-test :reload-all)
(run-tests 'your-ns.example-test)

我更喜欢保留user名称空间,而不像另一个回答所提到的那样使用in-ns更改它。相反,将命名空间作为参数传递给run-tests(如上所示)。

我还建议避免使用(use 'clojure.test);这就是为什么我建议在上面使用(require '[clojure.test :refer [run-tests]])。有关更多背景信息,请阅读http://dev.clojure.org/jira/browse/CLJ-879


1
值得在 require 'your-ns' 中添加 :refresh-all - Jakub M.
5
@JakubM 的确,但需要加上:reload-all才行:(require 'incanter.core-tests :reload-all) - Nils Blum-Oeste

19
在您上面的示例中,repl位于错误的命名空间中。如果将repl切换到core_test命名空间,然后运行(run-tests)可能会更好。
(in-ns 'first-project.core-test)
(run-tests)

另一种有趣的开发测试的方式是从 REPL 中运行它们,直到它们可以正常工作,因为测试是带有一些额外元数据的普通函数。

(in-ns 'first-project.core-test)
(my-test)

记得在调用in-ns函数之前要先加载文件。假设你的测试文件是tests/first_project/core_test.clj,那么你需要调用:

(load-file "tests/first_project/core_test.clj") (in-ns 'first-project.core-test)
(load "tests/first_project/core_test")
(in-ns 'first-project.core-test)
(my-test)

请记住,文件系统中的_在命名空间中变成了-,而/变成了.


2
在执行了 (in-ns 'first-project.core-test) 之后,REPL 就不再知道 run-tests 或 require/use 函数的命名空间了。我尝试了 (clojure.test/run-tests),但它没有找到任何测试(运行了 0 个测试)。 - anotherCode245
首先加载文件。在emacs中,这是ctrl-c ctrl-k。 - Arthur Ulfeldt
你也可以使用Ctrl-C Alt-N将REPL切换到命名空间。 - Arthur Ulfeldt
2
这个不起作用(运行Clojure 1.10)。没有找到任何测试。使用require的方式可以解决问题。这是因为in-ns只是为Clojure运行时设置“当前命名空间”,但并不从类文件或其他地方加载任何内容来实际填充该命名空间。 - David Tonhofer

1

简而言之:

require的使用方式

只有在先前发出了in-ns命令时才需要完全限定函数。然后执行以下操作:

(clojure.core/require '[clojure.core :refer [require]]
                      '[clojure.test :refer [run-tests]]
                      '[clojure.repl :refer [dir]])

; Load whatever is in namespace "foo.bar-test" and reload everything
; if `:reload-all` has been additionally given

(require 'foo.bar-test :reload-all) 
;=> nil

; List your tests for good measure (Note: don't quote the namespace symbol!)

(dir foo.bar-test)
;=> t-math
;=> t-arith
;=> t-exponential
;=> nil 

; Check meta-information on a test to verify selector for example 

(meta #'foo.bar-test/t-math)
;=> {:basic-math true, :test #object[foo.bar_tes...

; `run-tests` will probably run nothing because the current namespace
; doesn't contain any tests, unless you have changed it with "in-ns"

(run-tests) 
;=> Ran 0 tests containing 0 assertions.

; run tests by giving namespace explicitly instead

(run-tests 'foo.bar-test) 
;=> Ran 3 tests containing 29 assertions.

0

补充一下,如果你正在使用VsCode + Calva,你可以运行repl并运行当前命名空间的测试 ctrl+alt+c t


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接