最小化复现
`
(require 'clojure.test)
(clojure.test/deftest foo-test
(throw (ex-info "我失败" {})))
(clojure.test/deftest bar-test
(.println System/out "bar"))
(clojure.test/test-vars [#'foo-test #'bar-test])
`
结果
ERROR in (foo-test) (core.clj:4617) 未捕获异常,不在断言中。期望值: nil bar 实际: clojure.lang.ExceptionInfo: 我失败 at clojure.core$ex_info.invokeStatic (core.clj:4617) ...
注意 "bar" 在错误报告中间的部分{{foo-test}}输出中。
分析
{{(clojure.test/report {:type :error, :actual some-exception})}} 调用 {{stack/print-cause-trace}}。与其它 {{clojure.test/report}} 调用路径不同,这不会在换行时刷新。因此,当测试因异常失败且有内容直接写入 Java 的 {{System.out}} 时,错误报告的第一部分和异常追踪之间可能存在很大的间隔。
(为了解释为什么这很烦人:我们通过 {{clj-webdriver}} 运行 Selenium 测试,并通过 {{clojure.tools.logging}} 通过 log4j 记录系统中的测试。我们总是会在 "expected: ..." 和后续的 "actual: ..." 异常追踪之间看到几十甚至几百行。这使得在日志中出现的其他事件与失败发生的时间相混淆,很容易得出完全错误的结论。)
(在我个人看来,最好(如果 clojure.test/report 总是构造每个单独调用的输出为一个单独的字符串,并且将其一次性写入 * }) — 这样就不会有输出从其他线程中交错的可能性。如果没有那,至少如果 {{:error}} 实现调用 {{(flush)}},也会很有帮助。