Clojure中运行单元测试的“正确”方法

17

目前,我在编程会话开始时在REPL中定义以下函数:

(defn rt []
  (let [tns 'my.namespace-test]
    (use tns :reload-all)
    (cojure.test/test-ns tns)))

每次我做出改变,我都会重新运行测试:

user=>(rt)

这对我来说效果还算不错。但当我删除一个测试时,就必须重新启动REPL并重新定义该方法,有点麻烦。此外,我听说使用use函数可能会出现问题。因此我的问题是:

  • 以这种方式使用use会在将来给我带来问题吗?
  • 有比我当前做法更惯用的工作流程吗?
3个回答

18

大多数人都会跑步

lein test

从不同的终端运行测试,确保被测试的是文件中的内容而不是内存中的内容。如果你更改了函数名称,并仍然在某个地方调用旧名称,使用reload-all可能会导致错误的测试通过。

  • 像那样调用use本身并没有问题,只是在测试中使用更多的命名空间时会限制你不能有任何名称冲突。只要有一个,就可以了。
  • 使用lein让您指定单元测试和集成测试,并使用test-selectors功能轻松地将它们分组运行。

4
我最开始用 lein test 运行测试,但是和在 REPL 中运行相比,测试的运行时间更长了很多。这是否是正常现象,还是我操作有误? - Garrett Rowe
1
clojure.testexpectations、speclj 和 midje 都支持监视文件更改并自动运行测试(第一次加载除外,速度很快)。如果您使用 emacs,cider 有一个 clojure-test-mode,可以在 repl 上在 emacs 中运行测试,非常酷。 - xhh

12

我也在我的REPL中运行测试。我喜欢这样做,因为我对测试有更多的控制,并且由于JVM已经运行,所以速度更快。然而,正如你所说,很容易出问题。为了清理事情,我建议查看tools.namespace

特别是,您可以使用clojure.tools.namespace.repl/refresh重新加载在您的活动REPL中发生更改的文件。还有refresh-all用于重新加载类路径上的所有文件。

我将tools.namespace添加到我的:dev配置文件中的~/.lein/profiles.clj中,以便每个项目都可以使用它。然后,当您运行lein repl时,它将包含在类路径中,但不会泄漏到您项目的正式依赖项中。

当我在编写测试时,我会将其加载到我的REPL中并手动运行。测试只是一个无参数函数,因此您可以像这样调用它们。


7
我对 lein-midje 感到印象深刻。
执行命令 $ lein midje :autotest 启动一个clojure进程,监视src和test文件,重新加载相关的命名空间并运行与更改文件相关的测试(跟踪依赖项)。我使用VimShell将其与vim配合使用,开启一个分割窗口并同时打开源代码和测试文件。我在任意一个文件上进行修改,(相应的)测试就会在分割窗格中自动执行。

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